1use serde::{Deserialize, Serialize};
4
5use crate::{field_access, impl_cow, impl_default, impl_display};
6
7mod attachment;
8mod basic_channel;
9mod bot;
10mod bot_service;
11mod bot_type;
12mod channel_folder;
13mod channel_permission;
14mod client_capabilities;
15mod content_type;
16mod cross_realm_bot;
17mod custom_profile;
18mod default_channel_group;
19mod display_recipient;
20mod draft;
21mod edit_history;
22mod event_type;
23mod flag;
24mod giphy_rating_option;
25mod group_permission_setting;
26mod group_setting;
27mod include_subscribers;
28mod msg_type;
29mod muted_topic;
30mod muted_user;
31mod navigation_view;
32mod never_subscribed;
33mod onboarding_step;
34mod operation;
35mod presence;
36mod profile_data;
37mod propagate_mode;
38mod push_device;
39mod reaction;
40mod realm_authentication_method;
41mod realm_available_video_chat_provider;
42mod realm_billing;
43mod realm_create_private_stream_policy;
44mod realm_create_public_stream_policy;
45mod realm_create_web_public_stream_policy;
46mod realm_default_external_account;
47mod realm_domain;
48mod realm_embedded_bot;
49mod realm_emoji;
50mod realm_filter;
51mod realm_incoming_webhook_bot;
52mod realm_linkifier;
53mod realm_message_edit_history_visibility_policy;
54mod realm_organization_type;
55mod realm_plan_type;
56mod realm_playground;
57mod realm_user_settings_default;
58mod realm_video_chat_provider;
59mod realm_wildcard_mention_policy;
60mod recent_private_conversation;
61mod report_type;
62mod role;
63mod saved_snippet;
64mod scheduled_message;
65mod server_supported_permission_setting;
66mod server_thumbnail_format;
67mod submessage;
68mod subscription;
69mod to;
70mod topic_link;
71mod topics_policy;
72mod unread_msgs;
73mod user;
74mod user_group;
75mod user_settings;
76mod user_status;
77mod user_topic;
78mod webhook_config;
79
80pub mod delete_message;
81pub mod edit_message;
82pub mod emoji_reaction;
83pub mod fetch_api_key;
84pub mod get_file_temporary_url;
85pub mod get_message;
86pub mod get_message_history;
87pub mod get_messages;
88pub mod get_read_receipts;
89pub mod mark_all_as_read;
90pub mod mark_stream_as_read;
91pub mod mark_topic_as_read;
92pub mod matches_narrow;
93pub mod register;
94pub mod render;
95pub mod report_message;
96pub mod response;
97pub mod send_message;
98pub mod update_message_flags;
99pub mod update_message_flags_narrow;
100pub mod upload_file;
101
102pub use attachment::{Attachment, AttachmentMessage};
103pub use basic_channel::BasicChannel;
104pub use bot::Bot;
105pub use bot_service::{
106 BotService, BotServiceEmbedded, BotServiceOutgoingWebhook, OutgoingWebhookInterface,
107};
108pub use bot_type::BotType;
109pub use channel_folder::ChannelFolder;
110pub use channel_permission::{
111 CanAddSubscribersGroup, CanAdministerChannelGroup, CanDeleteAnyMessageGroup,
112 CanDeleteOwnMessageGroup, CanMoveMessagesOutOfChannelGroup, CanMoveMessagesWithinChannelGroup,
113 CanRemoveSubscribersGroup, CanResolveTopicsGroup, CanSendMessageGroup, CanSubscribeGroup,
114};
115pub use client_capabilities::ClientCapabilities;
116pub use content_type::ContentType;
117pub use cross_realm_bot::CrossRealmBot;
118pub use custom_profile::{CustomProfileField, CustomProfileFieldType};
119pub use default_channel_group::DefaultChannelGroup;
120pub use display_recipient::{DisplayRecipient, UserRecipient};
121pub use draft::{Draft, DraftType};
122pub use edit_history::EditHistory;
123pub use event_type::EventType;
124pub use flag::Flag;
125pub use giphy_rating_option::GiphyRatingOption;
126pub use group_permission_setting::GroupPermissionSetting;
127pub use group_setting::{GroupSetting, GroupSettingIds};
128pub use include_subscribers::IncludeSubscribers;
129pub use msg_type::MessageType;
130pub use muted_topic::MutedTopic;
131pub use muted_user::MutedUser;
132pub use navigation_view::NavigationView;
133pub use never_subscribed::NeverSubscribed;
134pub use onboarding_step::{OnboardingStep, OnboardingType};
135pub use operation::Operation;
136pub use presence::{
137 LegacyPresenceFormat, LegacyPresenceStatus, ModernPresenceFormat, Presence, PresenceList,
138};
139pub use profile_data::ProfileData;
140pub use propagate_mode::PropagateMode;
141pub use push_device::{PushDevice, PushDeviceStatus};
142pub use reaction::{Reaction, ReactionType};
143pub use realm_authentication_method::RealmAuthenticationMethod;
144pub use realm_available_video_chat_provider::RealmAvailableVideoChatProvider;
145pub use realm_billing::RealmBilling;
146pub use realm_create_private_stream_policy::RealmCreatePrivateStreamPolicy;
147pub use realm_create_public_stream_policy::RealmCreatePublicStreamPolicy;
148pub use realm_create_web_public_stream_policy::RealmCreateWebPublicStreamPolicy;
149pub use realm_default_external_account::RealmDefaultExternalAccount;
150pub use realm_domain::RealmDomain;
151pub use realm_embedded_bot::RealmEmbeddedBot;
152pub use realm_emoji::RealmEmoji;
153pub use realm_filter::RealmFilter;
154pub use realm_incoming_webhook_bot::RealmIncomingWebhookBot;
155pub use realm_linkifier::RealmLinkifier;
156pub use realm_message_edit_history_visibility_policy::RealmMessageEditHistoryVisibilityPolicy;
157pub use realm_organization_type::RealmOrganizationType;
158pub use realm_plan_type::RealmPlanType;
159pub use realm_playground::RealmPlayground;
160pub use realm_user_settings_default::*;
161pub use realm_video_chat_provider::RealmVideoChatProvider;
162pub use realm_wildcard_mention_policy::RealmWildcardMentionPolicy;
163pub use recent_private_conversation::RecentPrivateConversation;
164pub use report_type::ReportType;
165pub use role::Role;
166pub use saved_snippet::SavedSnippet;
167pub use scheduled_message::{ScheduledMessage, ScheduledMessageTo, ScheduledMessageType};
168pub use server_supported_permission_setting::ServerSupportedPermissionSetting;
169pub use server_thumbnail_format::ServerThumbnailFormat;
170pub use submessage::Submessage;
171pub use subscription::*;
172pub use to::MessageTo;
173pub use topic_link::TopicLink;
174pub use topics_policy::TopicsPolicy;
175pub use unread_msgs::{UnreadMsgs, UnreadMsgsHuddle, UnreadMsgsPm, UnreadMsgsStream};
176pub use user::User;
177pub use user_group::UserGroup;
178pub use user_settings::{UserSettings, UserSettingsEmojisetChoice};
179pub use user_status::UserStatus;
180pub use user_topic::UserTopic;
181pub use webhook_config::{WebhookConfigOption, WebhookUrlOption};
182
183#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
185pub struct Message {
186 #[serde(skip_serializing_if = "Option::is_none")]
187 avatar_url: Option<String>,
188 client: String,
189 content: String,
190 content_type: ContentType,
191 display_recipient: DisplayRecipient,
192 edit_history: Option<Vec<EditHistory>>,
193 id: u64,
194 is_me_message: bool,
195 last_edit_timestamp: Option<u64>,
196 last_moved_timestamp: Option<u64>,
197 reactions: Vec<Reaction>,
198 recipient_id: u64,
199 sender_email: String,
200 sender_full_name: String,
201 sender_id: u64,
202 sender_realm_str: String,
203 #[serde(skip_serializing_if = "Option::is_none")]
204 stream_id: Option<u64>,
205 subject: String,
206 submessages: Vec<Submessage>,
207 timestamp: u64,
208 #[serde(rename = "type")]
209 msg_type: MessageType,
210 flags: Vec<Flag>,
211 #[serde(skip_serializing_if = "Option::is_none")]
212 match_content: Option<String>,
213 #[serde(skip_serializing_if = "Option::is_none")]
214 match_subject: Option<String>,
215}
216
217impl Message {
218 pub const fn new() -> Self {
220 Self {
221 avatar_url: None,
222 client: String::new(),
223 content: String::new(),
224 content_type: ContentType::new(),
225 display_recipient: DisplayRecipient::new(),
226 edit_history: None,
227 id: 0,
228 is_me_message: false,
229 last_edit_timestamp: None,
230 last_moved_timestamp: None,
231 reactions: Vec::new(),
232 recipient_id: 0,
233 sender_email: String::new(),
234 sender_full_name: String::new(),
235 sender_id: 0,
236 sender_realm_str: String::new(),
237 stream_id: None,
238 subject: String::new(),
239 submessages: Vec::new(),
240 timestamp: 0,
241 msg_type: MessageType::new(),
242 flags: Vec::new(),
243 match_content: None,
244 match_subject: None,
245 }
246 }
247}
248
249field_access! {
250 Message {
251 avatar_url: option_cow_deref { str, String },
252 match_content: option_cow_deref { str, String },
253 match_subject: option_cow_deref { str, String },
254 edit_history: option_cow_deref { [EditHistory], Vec<EditHistory> },
255 }
256}
257
258field_access! {
259 Message {
260 client: cow { str },
261 content: cow { str },
262 display_recipient: cow { DisplayRecipient },
263 }
264}
265
266field_access! {
267 Message {
268 content_type: ContentType,
269 id: u64,
270 is_me_message: bool,
271 recipient_id: u64,
272 sender_id: u64,
273 timestamp: u64,
274 msg_type: MessageType,
275 }
276}
277
278field_access! {
279 Message {
280 last_edit_timestamp: option { u64 },
281 last_moved_timestamp: option { u64 },
282 stream_id: option { u64 },
283 }
284}
285
286field_access! {
287 Message {
288 reactions: cow { [Reaction] },
289 sender_email: cow { str },
290 sender_full_name: cow { str },
291 sender_realm_str: cow { str },
292 subject: cow { str },
293 submessages: cow { [Submessage] },
294 flags: cow { [Flag] },
295 }
296}
297
298impl_cow!(Message);
299impl_default!(Message);
300impl_display!(Message);
301
302#[cfg(test)]
303mod tests {
304 use super::*;
305
306 #[test]
307 fn test_message_minimal() {
308 let client = "client";
309 let content = "content";
310 let content_type = ContentType::Markdown;
311 let display_recipient = DisplayRecipient::Channel("recipient channel".into());
312 let id = 1;
313 let is_me_message = false;
314 let recipient_id = 4;
315 let sender_email = "sender@example.com";
316 let sender_full_name = "sender full name";
317 let sender_id = 5;
318 let sender_realm_str = "sender realm";
319 let subject = "test subject";
320 let timestamp = 7;
321 let msg_type = MessageType::Channel;
322
323 let message = Message::new()
324 .with_client(client)
325 .with_content(content)
326 .with_content_type(content_type)
327 .with_display_recipient(&display_recipient)
328 .with_id(id)
329 .with_is_me_message(is_me_message)
330 .with_recipient_id(recipient_id)
331 .with_sender_email(sender_email)
332 .with_sender_full_name(sender_full_name)
333 .with_sender_id(sender_id)
334 .with_sender_realm_str(sender_realm_str)
335 .with_subject(subject)
336 .with_timestamp(timestamp)
337 .with_msg_type(msg_type);
338
339 let message_json = message.to_string();
340
341 assert_eq!(message.client(), client);
342 assert_eq!(message.content(), content);
343 assert_eq!(message.content_type(), content_type);
344 assert_eq!(message.display_recipient(), &display_recipient);
345 assert_eq!(message.id(), id);
346 assert_eq!(message.is_me_message(), is_me_message);
347 assert_eq!(message.recipient_id(), recipient_id);
348 assert_eq!(message.sender_email(), sender_email);
349 assert_eq!(message.sender_full_name(), sender_full_name);
350 assert_eq!(message.sender_id(), sender_id);
351 assert_eq!(message.sender_realm_str(), sender_realm_str);
352 assert_eq!(message.subject(), subject);
353 assert_eq!(message.timestamp(), timestamp);
354 assert_eq!(message.msg_type(), msg_type);
355
356 assert_eq!(serde_json::to_string(&message).unwrap(), message_json);
357 assert_eq!(
358 serde_json::from_str::<Message>(&message_json).unwrap(),
359 message
360 );
361 }
362
363 #[test]
364 fn test_message_full() {
365 let avatar_url = "https://example.com/avatar";
366 let client = "client";
367 let content = "content";
368 let content_type = ContentType::Markdown;
369 let display_recipient = DisplayRecipient::Channel("recipient channel".into());
370 let id = 1;
371 let edit_history = [EditHistory::new()];
372 let is_me_message = false;
373 let last_edit_timestamp = 2;
374 let last_moved_timestamp = 3;
375 let reactions = [Reaction::new()];
376 let recipient_id = 4;
377 let sender_email = "sender@example.com";
378 let sender_full_name = "sender full name";
379 let sender_id = 5;
380 let sender_realm_str = "sender realm";
381 let stream_id = 6;
382 let subject = "test subject";
383 let submessages = [Submessage::new()];
384 let timestamp = 7;
385 let msg_type = MessageType::Channel;
386 let flags = [Flag::Historical];
387 let match_content = "match content";
388 let match_subject = "match subject";
389
390 let message = Message::new()
391 .with_avatar_url(avatar_url)
392 .with_client(client)
393 .with_content(content)
394 .with_content_type(content_type)
395 .with_display_recipient(&display_recipient)
396 .with_id(id)
397 .with_edit_history(edit_history.as_ref())
398 .with_is_me_message(is_me_message)
399 .with_last_edit_timestamp(last_edit_timestamp)
400 .with_last_moved_timestamp(last_moved_timestamp)
401 .with_reactions(reactions.as_ref())
402 .with_recipient_id(recipient_id)
403 .with_sender_email(sender_email)
404 .with_sender_full_name(sender_full_name)
405 .with_sender_id(sender_id)
406 .with_sender_realm_str(sender_realm_str)
407 .with_stream_id(stream_id)
408 .with_subject(subject)
409 .with_submessages(submessages.as_ref())
410 .with_timestamp(timestamp)
411 .with_msg_type(msg_type)
412 .with_flags(flags.as_ref())
413 .with_match_content(match_content)
414 .with_match_subject(match_subject);
415
416 let message_json = message.to_string();
417
418 assert_eq!(message.avatar_url(), Some(avatar_url));
419 assert_eq!(message.client(), client);
420 assert_eq!(message.content(), content);
421 assert_eq!(message.content_type(), content_type);
422 assert_eq!(message.display_recipient(), &display_recipient);
423 assert_eq!(message.id(), id);
424 assert_eq!(message.edit_history(), Some(edit_history.as_ref()));
425 assert_eq!(message.is_me_message(), is_me_message);
426 assert_eq!(message.last_edit_timestamp(), Some(last_edit_timestamp));
427 assert_eq!(message.last_moved_timestamp(), Some(last_moved_timestamp));
428 assert_eq!(message.reactions(), reactions.as_ref());
429 assert_eq!(message.recipient_id(), recipient_id);
430 assert_eq!(message.sender_email(), sender_email);
431 assert_eq!(message.sender_full_name(), sender_full_name);
432 assert_eq!(message.sender_id(), sender_id);
433 assert_eq!(message.sender_realm_str(), sender_realm_str);
434 assert_eq!(message.stream_id(), Some(stream_id));
435 assert_eq!(message.subject(), subject);
436 assert_eq!(message.submessages(), submessages.as_ref());
437 assert_eq!(message.timestamp(), timestamp);
438 assert_eq!(message.msg_type(), msg_type);
439 assert_eq!(message.flags(), flags.as_ref());
440 assert_eq!(message.match_content(), Some(match_content));
441 assert_eq!(message.match_subject(), Some(match_subject));
442
443 assert_eq!(serde_json::to_string(&message).unwrap(), message_json);
444 assert_eq!(
445 serde_json::from_str::<Message>(&message_json).unwrap(),
446 message
447 );
448 }
449}