1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3
4use super::{
5 message_contents::*, message_entity::*, raw::*, Game, InlineKeyboardMarkup, Invoice,
6 PassportData, Sticker, SuccessfulPayment, User,
7};
8
9#[derive(Debug, Clone, PartialEq)]
11pub struct Message {
12 pub message_id: i64,
14 pub from: Option<super::User>,
16 pub sender_chat: Option<super::Chat>,
21 pub date: DateTime<Utc>,
23 pub chat: super::Chat,
25
26 pub forward_data: Option<ForwardData>,
28
29 pub reply_to_message: Option<Box<Message>>,
30 pub via_bot: Option<User>,
32 pub edit_date: Option<DateTime<Utc>>,
34 pub author_signature: Option<String>,
36
37 pub content: MessageContent,
39
40 pub connected_website: Option<String>,
42 pub passport_data: Option<PassportData>,
44 pub reply_markup: Option<InlineKeyboardMarkup>,
47}
48
49#[allow(clippy::large_enum_variant)]
51#[derive(Debug, Clone, PartialEq)]
52pub enum MessageContent {
53 Text {
54 content: String,
56 entities: Vec<MessageEntity>,
59 },
60 Audio {
61 content: Audio,
63 caption: Option<String>,
65 caption_entities: Option<Vec<MessageEntity>>,
68 },
69 Document {
70 content: Document,
72 caption: Option<String>,
74 caption_entities: Option<Vec<MessageEntity>>,
77 },
78 Animation {
79 content: Animation,
81 caption: Option<String>,
83 caption_entities: Option<Vec<MessageEntity>>,
86 },
87 Video {
88 content: Video,
90 caption: Option<String>,
92 caption_entities: Option<Vec<MessageEntity>>,
95 media_group_id: Option<String>,
98 },
99 Voice {
100 content: Voice,
102 caption: Option<String>,
104 caption_entities: Option<Vec<MessageEntity>>,
107 },
108 Photo {
109 content: Vec<PhotoSize>,
111 caption: Option<String>,
113 caption_entities: Option<Vec<MessageEntity>>,
116 media_group_id: Option<String>,
119 },
120
121 Game {
122 content: Game,
124 },
125 Sticker {
126 content: Sticker,
128 },
129 VideoNote {
130 content: VideoNote,
132 },
133 Contact {
134 content: Contact,
136 },
137 Location {
138 content: Location,
140 },
141 Venue {
142 content: Venue,
144 },
145 Poll {
146 content: Poll,
148 },
149 Dice {
150 content: Dice,
152 },
153 NewChatMembers {
154 content: Vec<User>,
158 },
159 LeftChatMember {
160 content: User,
163 },
164 NewChatTitle {
165 content: String,
167 },
168 NewChatPhoto {
169 content: Vec<PhotoSize>,
171 },
172 MessageAutoDeleteTimerChanged {
173 content: MessageAutoDeleteTimerChanged,
175 },
176 MigrateToChatID {
177 content: i64,
180 },
181 MigrateFromChatID {
182 content: i64,
185 },
186 PinnedMessage {
187 content: Box<Message>,
191 },
192 Invoice {
193 content: Invoice,
198 },
199 SuccessfulPayment {
200 content: SuccessfulPayment,
203 },
204 ProximityAlertTriggered {
205 content: ProximityAlertTriggered,
208 },
209 VoiceChatScheduled {
210 content: VoiceChatScheduled,
212 },
213 VoiceChatStarted {
214 content: VoiceChatStarted,
216 },
217 VoiceChatEnded {
218 content: VoiceChatEnded,
220 },
221 VoiceChatParticipantsInvited {
222 content: VoiceChatParticipantsInvited,
224 },
225
226 DeleteChatPhoto,
228 GroupChatCreated,
230 SupergroupChatCreated,
236 ChannelChatCreated,
242 Unknown,
244}
245
246#[derive(Debug, Clone, PartialEq)]
248pub struct ForwardData {
249 pub from: Option<super::User>,
251 pub from_chat: Option<super::Chat>,
254 pub from_message_id: Option<i64>,
257 pub signature: Option<String>,
260 pub sender_name: Option<String>,
263 pub date: DateTime<Utc>,
265}
266
267impl Message {
268 pub fn get_text(&self) -> Option<String> {
269 match self.content {
270 MessageContent::Text { ref content, .. } => Some(content.clone()),
271 MessageContent::Audio { ref caption, .. }
272 | MessageContent::Document { ref caption, .. }
273 | MessageContent::Animation { ref caption, .. }
274 | MessageContent::Video { ref caption, .. }
275 | MessageContent::Voice { ref caption, .. }
276 | MessageContent::Photo { ref caption, .. } => caption.clone(),
277 _ => None,
278 }
279 }
280}
281
282impl From<RawMessage> for Message {
283 #[allow(clippy::too_many_lines)]
284 fn from(raw: RawMessage) -> Message {
285 let message_id = raw.message_id;
286 let from = raw.from;
287 let sender_chat = raw.sender_chat.map(std::convert::Into::into);
288 let date = raw.date;
289 let chat = raw.chat.into();
290 let reply_to_message = raw.reply_to_message.map(|r| Box::new((*r).into()));
291 let via_bot = raw.via_bot;
292 let edit_date = raw.edit_date;
293 let author_signature = raw.author_signature;
294 let connected_website = raw.connected_website;
295 let passport_data = raw.passport_data;
296 let reply_markup = raw.reply_markup;
297
298 let forward_data = if let Some(d) = raw.forward_date {
299 Some(ForwardData {
300 from: raw.forward_from,
301 from_chat: raw.forward_from_chat.map(std::convert::Into::into),
302 from_message_id: raw.forward_from_message_id,
303 signature: raw.forward_signature,
304 sender_name: raw.forward_sender_name,
305 date: d,
306 })
307 } else {
308 None
309 };
310
311 let fill_in_content = |content: MessageContent| Self {
312 message_id,
313 from,
314 sender_chat,
315 date,
316 chat,
317 forward_data,
318 reply_to_message,
319 via_bot,
320 edit_date,
321 author_signature,
322 content,
323 connected_website,
324 passport_data,
325 reply_markup,
326 };
327
328 if let Some(c) = raw.text {
329 return fill_in_content(MessageContent::Text {
330 content: c,
331 entities: raw.entities.unwrap_or_default(),
332 });
333 } else if let Some(c) = raw.video {
334 return fill_in_content(MessageContent::Video {
335 content: c,
336 caption: raw.caption,
337 caption_entities: raw.caption_entities,
338 media_group_id: raw.media_group_id,
339 });
340 } else if let Some(c) = raw.photo {
341 return fill_in_content(MessageContent::Photo {
342 content: c,
343 caption: raw.caption,
344 caption_entities: raw.caption_entities,
345 media_group_id: raw.media_group_id,
346 });
347 } else if let Some(c) = raw.pinned_message {
348 return fill_in_content(MessageContent::PinnedMessage {
349 content: Box::new((*c).into()),
350 });
351 }
352
353 macro_rules! content_with_captions {
354 ($data:expr, $kind:ident) => {
355 if let Some(c) = $data {
356 return fill_in_content(MessageContent::$kind {
357 content: c,
358 caption: raw.caption,
359 caption_entities: raw.caption_entities,
360 });
361 }
362 };
363 }
364
365 macro_rules! content {
366 ($data:expr, $kind:ident) => {
367 if let Some(c) = $data {
368 return fill_in_content(MessageContent::$kind { content: c });
369 }
370 };
371 }
372
373 macro_rules! bool_content {
374 ($data:expr, $kind:ident) => {
375 if $data {
376 return fill_in_content(MessageContent::$kind);
377 }
378 };
379 }
380
381 content_with_captions!(raw.audio, Audio);
382 content_with_captions!(raw.animation, Animation);
383 content_with_captions!(raw.document, Document);
384 content_with_captions!(raw.voice, Voice);
385
386 content!(raw.game, Game);
387 content!(raw.sticker, Sticker);
388 content!(raw.video_note, VideoNote);
389 content!(raw.contact, Contact);
390 content!(raw.location, Location);
391 content!(raw.venue, Venue);
392 content!(raw.poll, Poll);
393 content!(raw.dice, Dice);
394 content!(raw.new_chat_members, NewChatMembers);
395 content!(raw.left_chat_member, LeftChatMember);
396 content!(raw.new_chat_title, NewChatTitle);
397 content!(raw.new_chat_photo, NewChatPhoto);
398 content!(
399 raw.message_auto_delete_timer_changed,
400 MessageAutoDeleteTimerChanged
401 );
402 content!(raw.migrate_to_chat_id, MigrateToChatID);
403 content!(raw.migrate_from_chat_id, MigrateFromChatID);
404 content!(raw.invoice, Invoice);
405 content!(raw.successful_payment, SuccessfulPayment);
406 content!(raw.proximity_alert_triggered, ProximityAlertTriggered);
407 content!(raw.voice_chat_scheduled, VoiceChatScheduled);
408 content!(raw.voice_chat_started, VoiceChatStarted);
409 content!(raw.voice_chat_ended, VoiceChatEnded);
410 content!(
411 raw.voice_chat_participants_invited,
412 VoiceChatParticipantsInvited
413 );
414
415 bool_content!(raw.delete_chat_photo, DeleteChatPhoto);
416 bool_content!(raw.group_chat_created, GroupChatCreated);
417 bool_content!(raw.supergroup_chat_created, SupergroupChatCreated);
418 bool_content!(raw.channel_chat_created, ChannelChatCreated);
419
420 fill_in_content(MessageContent::Unknown)
421 }
422}
423
424impl From<Message> for RawMessage {
425 #[allow(clippy::too_many_lines)]
426 fn from(message: Message) -> RawMessage {
427 let mut ret = Self {
428 message_id: message.message_id,
429 from: message.from,
430 sender_chat: message.sender_chat.map(std::convert::Into::into),
431 date: message.date,
432 chat: message.chat.into(),
433 reply_to_message: message.reply_to_message.map(|r| Box::new((*r).into())),
434 via_bot: message.via_bot,
435 edit_date: message.edit_date,
436 media_group_id: None,
437 author_signature: message.author_signature,
438
439 forward_date: None,
440 forward_sender_name: None,
441 forward_signature: None,
442 forward_from_message_id: None,
443 forward_from: None,
444 forward_from_chat: None,
445
446 text: None,
447 entities: None,
448 caption_entities: None,
449 audio: None,
450 document: None,
451 animation: None,
452 game: None,
453 photo: None,
454 sticker: None,
455 video: None,
456 voice: None,
457 video_note: None,
458 caption: None,
459 contact: None,
460 location: None,
461 venue: None,
462 poll: None,
463 dice: None,
464 new_chat_members: None,
465 left_chat_member: None,
466 new_chat_title: None,
467 new_chat_photo: None,
468 delete_chat_photo: false,
469 group_chat_created: false,
470 supergroup_chat_created: false,
471 channel_chat_created: false,
472 message_auto_delete_timer_changed: None,
473 migrate_to_chat_id: None,
474 migrate_from_chat_id: None,
475 pinned_message: None,
476 invoice: None,
477 successful_payment: None,
478 proximity_alert_triggered: None,
479 voice_chat_scheduled: None,
480 voice_chat_started: None,
481 voice_chat_ended: None,
482 voice_chat_participants_invited: None,
483
484 connected_website: message.connected_website,
485 passport_data: message.passport_data,
486 reply_markup: message.reply_markup,
487 };
488
489 if let Some(d) = message.forward_data {
490 ret.forward_date = Some(d.date);
491 ret.forward_sender_name = d.sender_name;
492 ret.forward_signature = d.signature;
493 ret.forward_from_message_id = d.from_message_id;
494 ret.forward_from = d.from;
495 ret.forward_from_chat = d.from_chat.map(std::convert::Into::into);
496 }
497
498 match message.content {
499 MessageContent::Text { content, entities } => {
500 ret.text = Some(content);
501 ret.entities = Some(entities);
502 ret
503 }
504 MessageContent::Audio {
505 content,
506 caption,
507 caption_entities,
508 } => {
509 ret.audio = Some(content);
510 ret.caption = caption;
511 ret.caption_entities = caption_entities;
512 ret
513 }
514 MessageContent::Document {
515 content,
516 caption,
517 caption_entities,
518 } => {
519 ret.document = Some(content);
520 ret.caption = caption;
521 ret.caption_entities = caption_entities;
522 ret
523 }
524 MessageContent::Animation {
525 content,
526 caption,
527 caption_entities,
528 } => {
529 ret.animation = Some(content);
530 ret.caption = caption;
531 ret.caption_entities = caption_entities;
532 ret
533 }
534 MessageContent::Voice {
535 content,
536 caption,
537 caption_entities,
538 } => {
539 ret.voice = Some(content);
540 ret.caption = caption;
541 ret.caption_entities = caption_entities;
542 ret
543 }
544 MessageContent::Video {
545 content,
546 caption,
547 caption_entities,
548 media_group_id,
549 } => {
550 ret.video = Some(content);
551 ret.caption = caption;
552 ret.caption_entities = caption_entities;
553 ret.media_group_id = media_group_id;
554 ret
555 }
556 MessageContent::Photo {
557 content,
558 caption,
559 caption_entities,
560 media_group_id,
561 } => {
562 ret.photo = Some(content);
563 ret.caption = caption;
564 ret.caption_entities = caption_entities;
565 ret.media_group_id = media_group_id;
566 ret
567 }
568 MessageContent::Game { content } => {
569 ret.game = Some(content);
570 ret
571 }
572 MessageContent::Sticker { content } => {
573 ret.sticker = Some(content);
574 ret
575 }
576 MessageContent::VideoNote { content } => {
577 ret.video_note = Some(content);
578 ret
579 }
580 MessageContent::Contact { content } => {
581 ret.contact = Some(content);
582 ret
583 }
584 MessageContent::Location { content } => {
585 ret.location = Some(content);
586 ret
587 }
588 MessageContent::Venue { content } => {
589 ret.venue = Some(content);
590 ret
591 }
592 MessageContent::Poll { content } => {
593 ret.poll = Some(content);
594 ret
595 }
596 MessageContent::Dice { content } => {
597 ret.dice = Some(content);
598 ret
599 }
600 MessageContent::NewChatMembers { content } => {
601 ret.new_chat_members = Some(content);
602 ret
603 }
604 MessageContent::LeftChatMember { content } => {
605 ret.left_chat_member = Some(content);
606 ret
607 }
608 MessageContent::NewChatTitle { content } => {
609 ret.new_chat_title = Some(content);
610 ret
611 }
612 MessageContent::NewChatPhoto { content } => {
613 ret.new_chat_photo = Some(content);
614 ret
615 }
616 MessageContent::MessageAutoDeleteTimerChanged { content } => {
617 ret.message_auto_delete_timer_changed = Some(content);
618 ret
619 }
620 MessageContent::MigrateToChatID { content } => {
621 ret.migrate_to_chat_id = Some(content);
622 ret
623 }
624 MessageContent::MigrateFromChatID { content } => {
625 ret.migrate_from_chat_id = Some(content);
626 ret
627 }
628 MessageContent::Invoice { content } => {
629 ret.invoice = Some(content);
630 ret
631 }
632 MessageContent::SuccessfulPayment { content } => {
633 ret.successful_payment = Some(content);
634 ret
635 }
636 MessageContent::PinnedMessage { content } => {
637 ret.pinned_message = Some(Box::new((*content).into()));
638 ret
639 }
640 MessageContent::ProximityAlertTriggered { content } => {
641 ret.proximity_alert_triggered = Some(content);
642 ret
643 }
644 MessageContent::VoiceChatScheduled { content } => {
645 ret.voice_chat_scheduled = Some(content);
646 ret
647 }
648 MessageContent::VoiceChatStarted { content } => {
649 ret.voice_chat_started = Some(content);
650 ret
651 }
652 MessageContent::VoiceChatEnded { content } => {
653 ret.voice_chat_ended = Some(content);
654 ret
655 }
656 MessageContent::VoiceChatParticipantsInvited { content } => {
657 ret.voice_chat_participants_invited = Some(content);
658 ret
659 }
660 MessageContent::DeleteChatPhoto => {
661 ret.delete_chat_photo = true;
662 ret
663 }
664 MessageContent::GroupChatCreated => {
665 ret.group_chat_created = true;
666 ret
667 }
668 MessageContent::SupergroupChatCreated => {
669 ret.supergroup_chat_created = true;
670 ret
671 }
672 MessageContent::ChannelChatCreated => {
673 ret.channel_chat_created = true;
674 ret
675 }
676 MessageContent::Unknown => ret,
677 }
678 }
679}
680
681impl<'de> Deserialize<'de> for Message {
682 fn deserialize<D>(deserializer: D) -> Result<Message, D::Error>
683 where
684 D: Deserializer<'de>,
685 {
686 let raw: RawMessage = Deserialize::deserialize(deserializer)?;
687
688 Ok(raw.into())
689 }
690}
691
692impl Serialize for Message {
693 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
694 where
695 S: Serializer,
696 {
697 RawMessage::from(self.clone()).serialize(serializer)
698 }
699}
700
701#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
703pub struct MessageId {
704 pub message_id: i64,
706}