Skip to main content

tgbot/types/definitions/rich/
message.rs

1use serde::{Deserialize, Serialize};
2
3use super::block::RichBlock;
4use crate::{
5    api::{Method, Payload},
6    types::{ChatId, Integer, Message, ReplyMarkup, ReplyParameters, SuggestedPostParameters},
7};
8
9/// Rich formatted message.
10#[serde_with::skip_serializing_none]
11#[derive(Clone, Debug, Deserialize, Serialize)]
12pub struct RichMessage {
13    /// Content of the message.
14    pub blocks: Vec<RichBlock>,
15    /// Whether the message must be show right-to-left.
16    pub is_rtl: Option<bool>,
17}
18
19impl<A, B> From<A> for RichMessage
20where
21    A: IntoIterator<Item = B>,
22    B: Into<RichBlock>,
23{
24    fn from(value: A) -> Self {
25        Self::from_iter(value)
26    }
27}
28
29impl<I> FromIterator<I> for RichMessage
30where
31    I: Into<RichBlock>,
32{
33    fn from_iter<T>(value: T) -> Self
34    where
35        T: IntoIterator<Item = I>,
36    {
37        Self {
38            blocks: value.into_iter().map(Into::into).collect(),
39            is_rtl: None,
40        }
41    }
42}
43
44impl RichMessage {
45    /// Sets a new value for the `is_rtl` flag.
46    ///
47    /// # Arguments
48    ///
49    /// * `value` - Whether the message must be shown right-to-left.
50    pub fn with_is_rtl(mut self, value: bool) -> Self {
51        self.is_rtl = Some(value);
52        self
53    }
54}
55
56/// Describes a rich message to be sent.
57#[serde_with::skip_serializing_none]
58#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
59pub struct InputRichMessage {
60    html: Option<String>,
61    markdown: Option<String>,
62    is_rtl: Option<bool>,
63    skip_entity_detection: Option<bool>,
64}
65
66impl InputRichMessage {
67    /// Creates a new `InputRichMessage`.
68    ///
69    /// # Arguments
70    ///
71    /// * `value` - Content of the rich message to send described using Markdown formatting.
72    pub fn markdown<T>(value: T) -> Self
73    where
74        T: Into<String>,
75    {
76        Self {
77            html: None,
78            markdown: Some(value.into()),
79            is_rtl: None,
80            skip_entity_detection: None,
81        }
82    }
83
84    /// Creates a new `InputRichMessage`.
85    ///
86    /// # Arguments
87    ///
88    /// * `value` - Content of the rich message to send described using HTML formatting.
89    pub fn html<T>(value: T) -> Self
90    where
91        T: Into<String>,
92    {
93        Self {
94            html: Some(value.into()),
95            markdown: None,
96            is_rtl: None,
97            skip_entity_detection: None,
98        }
99    }
100
101    /// Sets a new value for the `is_rtl` flag.
102    ///
103    /// # Arguments
104    ///
105    /// * `value` - Whether the rich message must be shown right-to-left.
106    pub fn with_is_rtl(mut self, value: bool) -> Self {
107        self.is_rtl = Some(value);
108        self
109    }
110
111    /// Sets a new value for the `skip_entity_detection` flag.
112    ///
113    /// # Arguments
114    ///
115    /// * `value` - Whethert to skip automatic detection of entities in the text.
116    pub fn with_skip_entity_detection(mut self, value: bool) -> Self {
117        self.skip_entity_detection = Some(value);
118        self
119    }
120}
121
122/// Sends rich messages.
123///
124/// If the message contains a block with a media element,
125/// then the bot must have the right to send the media to the chat.
126#[serde_with::skip_serializing_none]
127#[derive(Clone, Debug, Serialize)]
128pub struct SendRichMessage {
129    chat_id: ChatId,
130    rich_message: InputRichMessage,
131    allow_paid_broadcast: Option<bool>,
132    business_connection_id: Option<String>,
133    direct_messages_topic_id: Option<Integer>,
134    disable_notification: Option<bool>,
135    message_effect_id: Option<String>,
136    message_thread_id: Option<Integer>,
137    protect_content: Option<bool>,
138    reply_markup: Option<ReplyMarkup>,
139    reply_parameters: Option<ReplyParameters>,
140    suggested_post_parameters: Option<SuggestedPostParameters>,
141}
142
143impl SendRichMessage {
144    /// Creates a new `SendRichMessage`.
145    ///
146    /// # Arguments
147    ///
148    /// * `chat_id` - Unique identifier of the target chat.
149    /// * `rich_message` - The message to be sent.
150    pub fn new<T>(chat_id: T, rich_message: InputRichMessage) -> Self
151    where
152        T: Into<ChatId>,
153    {
154        Self {
155            chat_id: chat_id.into(),
156            rich_message,
157            allow_paid_broadcast: None,
158            business_connection_id: None,
159            direct_messages_topic_id: None,
160            disable_notification: None,
161            message_effect_id: None,
162            message_thread_id: None,
163            protect_content: None,
164            reply_markup: None,
165            reply_parameters: None,
166            suggested_post_parameters: None,
167        }
168    }
169
170    /// Sets a new value for the `allow_paid_broadcast` flag.
171    ///
172    /// # Arguments
173    ///
174    /// * `value` - Whether to allow up to 1000 messages per second,
175    ///   ignoring broadcasting limits for a fee of 0.1 Telegram Stars per message.
176    ///
177    /// The relevant Stars will be withdrawn from the bot's balance.
178    pub fn with_allow_paid_broadcast(mut self, value: bool) -> Self {
179        self.allow_paid_broadcast = Some(value);
180        self
181    }
182
183    /// Sets a new business connection ID.
184    ///
185    /// # Arguments
186    ///
187    /// * `value` - Unique identifier of the business connection.
188    pub fn with_business_connection_id<T>(mut self, value: T) -> Self
189    where
190        T: Into<String>,
191    {
192        self.business_connection_id = Some(value.into());
193        self
194    }
195
196    /// Sets a new direct messages topic ID
197    ///
198    /// * `value` - Identifier of the direct messages topic to which the message will be sent.
199    ///
200    /// Required if the message is sent to a direct messages chat.
201    pub fn with_direct_messages_topic_id(mut self, value: Integer) -> Self {
202        self.direct_messages_topic_id = Some(value);
203        self
204    }
205
206    /// Sets a new value for the `disable_notification` flag.
207    ///
208    /// # Arguments
209    ///
210    /// * `value` - Indicates whether to send the message silently or not;
211    ///   a user will receive a notification without sound.
212    pub fn with_disable_notification(mut self, value: bool) -> Self {
213        self.disable_notification = Some(value);
214        self
215    }
216
217    /// Sets a new message effect ID.
218    ///
219    /// # Arguments
220    ///
221    /// * `value` - Unique identifier of the message effect to be added to the message; for private chats only.
222    pub fn with_message_effect_id<T>(mut self, value: T) -> Self
223    where
224        T: Into<String>,
225    {
226        self.message_effect_id = Some(value.into());
227        self
228    }
229
230    /// Sets a new message thread ID.
231    ///
232    /// # Arguments
233    ///
234    /// * `value` - Unique identifier of the target message thread;
235    ///   for forum supergroups and private chats of bots with forum topic mode enabled only.
236    pub fn with_message_thread_id(mut self, value: Integer) -> Self {
237        self.message_thread_id = Some(value);
238        self
239    }
240
241    /// Sets a new value for the `protect_content` flag.
242    ///
243    /// # Arguments
244    ///
245    /// * `value` - Indicates whether to protect the contents
246    ///   of the sent message from forwarding and saving.
247    pub fn with_protect_content(mut self, value: bool) -> Self {
248        self.protect_content = Some(value);
249        self
250    }
251
252    /// Sets a new reply markup.
253    ///
254    /// # Arguments
255    ///
256    /// * `value` - Reply markup.
257    pub fn with_reply_markup<T>(mut self, value: T) -> Self
258    where
259        T: Into<ReplyMarkup>,
260    {
261        self.reply_markup = Some(value.into());
262        self
263    }
264
265    /// Sets new reply parameters.
266    ///
267    /// # Arguments
268    ///
269    /// * `value` - Description of the message to reply to.
270    pub fn with_reply_parameters(mut self, value: ReplyParameters) -> Self {
271        self.reply_parameters = Some(value);
272        self
273    }
274
275    /// Sets a new suggested post parameters.
276    ///
277    /// # Arguments
278    ///
279    /// * `value` - An object containing the parameters of the suggested post to send.
280    ///
281    /// For direct messages chats only.
282    ///
283    /// If the message is sent as a reply to another suggested post, then that suggested post is automatically declined.
284    pub fn with_suggested_post_parameters(mut self, value: SuggestedPostParameters) -> Self {
285        self.suggested_post_parameters = Some(value);
286        self
287    }
288}
289
290impl Method for SendRichMessage {
291    type Response = Message;
292
293    fn into_payload(self) -> Payload {
294        Payload::json("sendRichMessage", self)
295    }
296}
297
298/// Streams a partial rich message to a user while the message is being generated.
299///
300/// Note that streamed draft is ephemeral and acts as a temporary
301/// 30-second preview - once the output is finalized.
302///
303/// You must call [`crate::types::SendRichMessage`] with the complete message
304/// to persist it in the user's chat.
305#[serde_with::skip_serializing_none]
306#[derive(Clone, Debug, Serialize)]
307pub struct SendRichMessageDraft {
308    chat_id: Integer,
309    draft_id: Integer,
310    rich_message: InputRichMessage,
311    message_thread_id: Option<Integer>,
312}
313
314impl SendRichMessageDraft {
315    /// Creates a new `SendRichMessageDraft`.
316    ///
317    /// # Arguments
318    ///
319    /// * `chat_id` - Unique identifier of the target chat.
320    /// * `draft_id` - Unique identifier of the message draft; must be non-zero;
321    ///   changes to drafts with the same identifier are animated.
322    /// * `rich_message` - The partial message to be streamed.
323    pub fn new(chat_id: Integer, draft_id: Integer, rich_message: InputRichMessage) -> Self {
324        Self {
325            chat_id,
326            draft_id,
327            rich_message,
328            message_thread_id: None,
329        }
330    }
331
332    /// Sets a new message thread ID.
333    ///
334    /// # Arguments
335    ///
336    /// * `value` - Unique identifier of the target message thread;
337    ///   for forum supergroups and private chats of bots with forum topic mode enabled only.
338    pub fn with_message_thread_id(mut self, value: Integer) -> Self {
339        self.message_thread_id = Some(value);
340        self
341    }
342}
343
344impl Method for SendRichMessageDraft {
345    type Response = bool;
346
347    fn into_payload(self) -> Payload {
348        Payload::json("sendRichMessageDraft", self)
349    }
350}