1use serde::{Deserialize, Serialize};
2
3use crate::file::{Animation, Audio, PhotoSize, Video, Voice};
4use crate::user::User;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
16#[serde(untagged)]
17pub enum RichText {
18 Plain(String),
20 Array(Vec<RichText>),
22 Bold(Box<RichTextBold>),
24 Italic(Box<RichTextItalic>),
26 Underline(Box<RichTextUnderline>),
28 Strikethrough(Box<RichTextStrikethrough>),
30 Spoiler(Box<RichTextSpoiler>),
32 DateTime(Box<RichTextDateTime>),
34 TextMention(Box<RichTextTextMention>),
36 Subscript(Box<RichTextSubscript>),
38 Superscript(Box<RichTextSuperscript>),
40 Marked(Box<RichTextMarked>),
42 Code(Box<RichTextCode>),
44 CustomEmoji(Box<RichTextCustomEmoji>),
46 MathematicalExpression(Box<RichTextMathematicalExpression>),
48 Url(Box<RichTextUrl>),
50 EmailAddress(Box<RichTextEmailAddress>),
52 PhoneNumber(Box<RichTextPhoneNumber>),
54 BankCardNumber(Box<RichTextBankCardNumber>),
56 Mention(Box<RichTextMention>),
58 Hashtag(Box<RichTextHashtag>),
60 Cashtag(Box<RichTextCashtag>),
62 BotCommand(Box<RichTextBotCommand>),
64 Anchor(Box<RichTextAnchor>),
66 AnchorLink(Box<RichTextAnchorLink>),
68 Footnote(Box<RichTextFootnote>),
70 Reference(Box<RichTextReference>),
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct RichTextBold {
77 #[serde(rename = "type")]
79 pub kind: String,
80 pub text: RichText,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct RichTextItalic {
87 #[serde(rename = "type")]
89 pub kind: String,
90 pub text: RichText,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct RichTextUnderline {
97 #[serde(rename = "type")]
99 pub kind: String,
100 pub text: RichText,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
106pub struct RichTextStrikethrough {
107 #[serde(rename = "type")]
109 pub kind: String,
110 pub text: RichText,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct RichTextSpoiler {
117 #[serde(rename = "type")]
119 pub kind: String,
120 pub text: RichText,
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct RichTextDateTime {
127 #[serde(rename = "type")]
129 pub kind: String,
130 pub text: RichText,
132 pub unix_time: i64,
134 pub date_time_format: String,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct RichTextTextMention {
141 #[serde(rename = "type")]
143 pub kind: String,
144 pub text: RichText,
146 pub user: User,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct RichTextSubscript {
153 #[serde(rename = "type")]
155 pub kind: String,
156 pub text: RichText,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
162pub struct RichTextSuperscript {
163 #[serde(rename = "type")]
165 pub kind: String,
166 pub text: RichText,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct RichTextMarked {
173 #[serde(rename = "type")]
175 pub kind: String,
176 pub text: RichText,
178}
179
180#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct RichTextCode {
183 #[serde(rename = "type")]
185 pub kind: String,
186 pub text: RichText,
188}
189
190#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct RichTextCustomEmoji {
193 #[serde(rename = "type")]
195 pub kind: String,
196 pub custom_emoji_id: String,
198 pub alternative_text: String,
200}
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
204pub struct RichTextMathematicalExpression {
205 #[serde(rename = "type")]
207 pub kind: String,
208 pub expression: String,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
214pub struct RichTextUrl {
215 #[serde(rename = "type")]
217 pub kind: String,
218 pub text: RichText,
220 pub url: String,
222}
223
224#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct RichTextEmailAddress {
227 #[serde(rename = "type")]
229 pub kind: String,
230 pub text: RichText,
232 pub email_address: String,
234}
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
238pub struct RichTextPhoneNumber {
239 #[serde(rename = "type")]
241 pub kind: String,
242 pub text: RichText,
244 pub phone_number: String,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
250pub struct RichTextBankCardNumber {
251 #[serde(rename = "type")]
253 pub kind: String,
254 pub text: RichText,
256 pub bank_card_number: String,
258}
259
260#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct RichTextMention {
263 #[serde(rename = "type")]
265 pub kind: String,
266 pub text: RichText,
268 pub username: String,
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize)]
274pub struct RichTextHashtag {
275 #[serde(rename = "type")]
277 pub kind: String,
278 pub text: RichText,
280 pub hashtag: String,
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
286pub struct RichTextCashtag {
287 #[serde(rename = "type")]
289 pub kind: String,
290 pub text: RichText,
292 pub cashtag: String,
294}
295
296#[derive(Debug, Clone, Serialize, Deserialize)]
298pub struct RichTextBotCommand {
299 #[serde(rename = "type")]
301 pub kind: String,
302 pub text: RichText,
304 pub bot_command: String,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
310pub struct RichTextAnchor {
311 #[serde(rename = "type")]
313 pub kind: String,
314 pub name: String,
316}
317
318#[derive(Debug, Clone, Serialize, Deserialize)]
322pub struct RichTextAnchorLink {
323 #[serde(rename = "type")]
325 pub kind: String,
326 pub text: RichText,
328 pub anchor_name: String,
330}
331
332#[derive(Debug, Clone, Serialize, Deserialize)]
334pub struct RichTextFootnote {
335 #[serde(rename = "type")]
337 pub kind: String,
338 pub text: RichText,
340 pub name: String,
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct RichTextReference {
347 #[serde(rename = "type")]
349 pub kind: String,
350 pub text: RichText,
352 pub footnote_name: String,
354}
355
356#[derive(Debug, Clone, Serialize, Deserialize)]
360pub struct RichBlockCaption {
361 pub text: RichText,
363 #[serde(skip_serializing_if = "Option::is_none")]
365 pub credit: Option<RichText>,
366}
367
368#[derive(Debug, Clone, Serialize, Deserialize)]
370pub struct RichBlockTableCell {
371 #[serde(skip_serializing_if = "Option::is_none")]
373 pub text: Option<RichText>,
374 #[serde(skip_serializing_if = "Option::is_none")]
376 pub is_header: Option<bool>,
377 #[serde(skip_serializing_if = "Option::is_none")]
379 pub colspan: Option<u32>,
380 #[serde(skip_serializing_if = "Option::is_none")]
382 pub rowspan: Option<u32>,
383 pub align: String,
385 pub valign: String,
387}
388
389#[derive(Debug, Clone, Serialize, Deserialize)]
391pub struct RichBlockListItem {
392 pub label: String,
394 pub blocks: Vec<RichBlock>,
396 #[serde(skip_serializing_if = "Option::is_none")]
398 pub has_checkbox: Option<bool>,
399 #[serde(skip_serializing_if = "Option::is_none")]
401 pub is_checked: Option<bool>,
402 #[serde(skip_serializing_if = "Option::is_none")]
404 pub value: Option<i64>,
405 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
407 pub kind: Option<String>,
408}
409
410#[derive(Debug, Clone, Serialize, Deserialize)]
416#[serde(tag = "type", rename_all = "snake_case")]
417pub enum RichBlock {
418 Paragraph(RichBlockParagraph),
420 #[serde(rename = "heading")]
422 SectionHeading(RichBlockSectionHeading),
423 Pre(RichBlockPreformatted),
425 Footer(RichBlockFooter),
427 Divider(RichBlockDivider),
429 MathematicalExpression(RichBlockMathematicalExpression),
431 Anchor(RichBlockAnchor),
433 List(RichBlockList),
435 Blockquote(RichBlockBlockQuotation),
437 Pullquote(RichBlockPullQuotation),
439 Collage(RichBlockCollage),
441 Slideshow(RichBlockSlideshow),
443 Table(RichBlockTable),
445 Details(RichBlockDetails),
447 Map(RichBlockMap),
449 Animation(RichBlockAnimation),
451 Audio(RichBlockAudio),
453 Photo(RichBlockPhoto),
455 Video(RichBlockVideo),
457 VoiceNote(RichBlockVoiceNote),
459 Thinking(RichBlockThinking),
463}
464
465#[derive(Debug, Clone, Serialize, Deserialize)]
467pub struct RichBlockParagraph {
468 pub text: RichText,
470}
471
472#[derive(Debug, Clone, Serialize, Deserialize)]
474pub struct RichBlockSectionHeading {
475 pub text: RichText,
477 pub size: u8,
479}
480
481#[derive(Debug, Clone, Serialize, Deserialize)]
483pub struct RichBlockPreformatted {
484 pub text: RichText,
486 #[serde(skip_serializing_if = "Option::is_none")]
488 pub language: Option<String>,
489}
490
491#[derive(Debug, Clone, Serialize, Deserialize)]
493pub struct RichBlockFooter {
494 pub text: RichText,
496}
497
498#[derive(Debug, Clone, Serialize, Deserialize)]
502pub struct RichBlockDivider {}
503
504#[derive(Debug, Clone, Serialize, Deserialize)]
506pub struct RichBlockMathematicalExpression {
507 pub expression: String,
509}
510
511#[derive(Debug, Clone, Serialize, Deserialize)]
513pub struct RichBlockAnchor {
514 pub name: String,
516}
517
518#[derive(Debug, Clone, Serialize, Deserialize)]
520pub struct RichBlockList {
521 pub items: Vec<RichBlockListItem>,
523}
524
525#[derive(Debug, Clone, Serialize, Deserialize)]
527pub struct RichBlockBlockQuotation {
528 pub blocks: Vec<RichBlock>,
530 #[serde(skip_serializing_if = "Option::is_none")]
532 pub credit: Option<RichText>,
533}
534
535#[derive(Debug, Clone, Serialize, Deserialize)]
537pub struct RichBlockPullQuotation {
538 pub text: RichText,
540 #[serde(skip_serializing_if = "Option::is_none")]
542 pub credit: Option<RichText>,
543}
544
545#[derive(Debug, Clone, Serialize, Deserialize)]
547pub struct RichBlockCollage {
548 pub blocks: Vec<RichBlock>,
550 #[serde(skip_serializing_if = "Option::is_none")]
552 pub caption: Option<RichBlockCaption>,
553}
554
555#[derive(Debug, Clone, Serialize, Deserialize)]
557pub struct RichBlockSlideshow {
558 pub blocks: Vec<RichBlock>,
560 #[serde(skip_serializing_if = "Option::is_none")]
562 pub caption: Option<RichBlockCaption>,
563}
564
565#[derive(Debug, Clone, Serialize, Deserialize)]
567pub struct RichBlockTable {
568 pub cells: Vec<Vec<RichBlockTableCell>>,
570 #[serde(skip_serializing_if = "Option::is_none")]
572 pub is_bordered: Option<bool>,
573 #[serde(skip_serializing_if = "Option::is_none")]
575 pub is_striped: Option<bool>,
576 #[serde(skip_serializing_if = "Option::is_none")]
578 pub caption: Option<RichText>,
579}
580
581#[derive(Debug, Clone, Serialize, Deserialize)]
583pub struct RichBlockDetails {
584 pub summary: RichText,
586 pub blocks: Vec<RichBlock>,
588 #[serde(skip_serializing_if = "Option::is_none")]
590 pub is_open: Option<bool>,
591}
592
593#[derive(Debug, Clone, Serialize, Deserialize)]
595pub struct RichBlockMap {
596 pub latitude: f64,
598 pub longitude: f64,
600 pub zoom: u8,
602 pub width: u32,
604 pub height: u32,
606 #[serde(skip_serializing_if = "Option::is_none")]
608 pub caption: Option<RichBlockCaption>,
609}
610
611#[derive(Debug, Clone, Serialize, Deserialize)]
613pub struct RichBlockAnimation {
614 pub animation: Animation,
616 #[serde(skip_serializing_if = "Option::is_none")]
618 pub need_autoplay: Option<bool>,
619 #[serde(skip_serializing_if = "Option::is_none")]
621 pub has_spoiler: Option<bool>,
622 #[serde(skip_serializing_if = "Option::is_none")]
624 pub caption: Option<RichBlockCaption>,
625}
626
627#[derive(Debug, Clone, Serialize, Deserialize)]
629pub struct RichBlockAudio {
630 pub audio: Audio,
632 #[serde(skip_serializing_if = "Option::is_none")]
634 pub caption: Option<RichBlockCaption>,
635}
636
637#[derive(Debug, Clone, Serialize, Deserialize)]
639pub struct RichBlockPhoto {
640 pub photo: Vec<PhotoSize>,
642 #[serde(skip_serializing_if = "Option::is_none")]
644 pub has_spoiler: Option<bool>,
645 #[serde(skip_serializing_if = "Option::is_none")]
647 pub caption: Option<RichBlockCaption>,
648}
649
650#[derive(Debug, Clone, Serialize, Deserialize)]
652pub struct RichBlockVideo {
653 pub video: Video,
655 #[serde(skip_serializing_if = "Option::is_none")]
657 pub need_autoplay: Option<bool>,
658 #[serde(skip_serializing_if = "Option::is_none")]
660 pub is_looped: Option<bool>,
661 #[serde(skip_serializing_if = "Option::is_none")]
663 pub has_spoiler: Option<bool>,
664 #[serde(skip_serializing_if = "Option::is_none")]
666 pub caption: Option<RichBlockCaption>,
667}
668
669#[derive(Debug, Clone, Serialize, Deserialize)]
671pub struct RichBlockVoiceNote {
672 pub voice_note: Voice,
674 #[serde(skip_serializing_if = "Option::is_none")]
676 pub caption: Option<RichBlockCaption>,
677}
678
679#[derive(Debug, Clone, Serialize, Deserialize)]
684pub struct RichBlockThinking {
685 pub text: RichText,
687}
688
689#[derive(Debug, Clone, Serialize, Deserialize)]
695pub struct RichMessage {
696 pub blocks: Vec<RichBlock>,
698 #[serde(skip_serializing_if = "Option::is_none")]
700 pub is_rtl: Option<bool>,
701}
702
703#[derive(Debug, Clone, Serialize, Deserialize)]
709pub struct InputRichMessage {
710 #[serde(skip_serializing_if = "Option::is_none")]
714 pub html: Option<String>,
715 #[serde(skip_serializing_if = "Option::is_none")]
719 pub markdown: Option<String>,
720 #[serde(skip_serializing_if = "Option::is_none")]
722 pub is_rtl: Option<bool>,
723 #[serde(skip_serializing_if = "Option::is_none")]
725 pub skip_entity_detection: Option<bool>,
726}
727
728impl InputRichMessage {
729 pub fn from_html(html: impl Into<String>) -> Self {
731 Self {
732 html: Some(html.into()),
733 markdown: None,
734 is_rtl: None,
735 skip_entity_detection: None,
736 }
737 }
738
739 pub fn from_markdown(markdown: impl Into<String>) -> Self {
741 Self {
742 html: None,
743 markdown: Some(markdown.into()),
744 is_rtl: None,
745 skip_entity_detection: None,
746 }
747 }
748
749 #[must_use]
751 pub fn rtl(mut self, v: bool) -> Self {
752 self.is_rtl = Some(v);
753 self
754 }
755
756 #[must_use]
758 pub fn skip_entity_detection(mut self, v: bool) -> Self {
759 self.skip_entity_detection = Some(v);
760 self
761 }
762}
763
764#[derive(Debug, Clone, Serialize, Deserialize)]
766pub struct InputRichMessageContent {
767 pub rich_message: InputRichMessage,
769}