tgbot/types/message/mod.rs
1use serde::{Deserialize, Deserializer, Serialize};
2
3pub use self::{command::*, data::*, methods::*, origin::*, quote::*, reply::*, sender::*};
4use crate::types::{Chat, InlineKeyboardMarkup, Integer, LinkPreviewOptions, Text, User};
5
6#[cfg(test)]
7mod tests;
8
9mod command;
10mod data;
11mod methods;
12mod origin;
13mod quote;
14mod reply;
15mod sender;
16
17/// Represents a result of `EditMessage*` requests.
18#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
19#[allow(clippy::large_enum_variant)]
20#[serde(untagged)]
21pub enum EditMessageResult {
22 /// Returned if edited message is sent by the bot.
23 Message(Message),
24 /// Returned if edited message is NOT sent by the bot.
25 Bool(bool),
26}
27
28/// Describes a message that was deleted or is otherwise inaccessible to the bot.
29#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
30pub struct InaccessibleMessage {
31 /// Chat the message belonged to.
32 pub chat: Chat,
33 /// Unique message identifier inside the chat
34 pub message_id: Integer,
35}
36
37/// Describes a message that can be inaccessible to the bot.
38#[derive(Clone, Debug, derive_more::From, PartialEq, Serialize)]
39#[serde(untagged)]
40pub enum MaybeInaccessibleMessage {
41 /// Describes a message that was deleted or is otherwise inaccessible to the bot.
42 InaccessibleMessage(InaccessibleMessage),
43 /// Describes a regular message.
44 Message(Box<Message>),
45}
46
47impl<'de> Deserialize<'de> for MaybeInaccessibleMessage {
48 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
49 where
50 D: Deserializer<'de>,
51 {
52 Message::deserialize(deserializer).map(|x| {
53 if x.date == 0 {
54 Self::InaccessibleMessage(InaccessibleMessage {
55 chat: x.chat,
56 message_id: x.id,
57 })
58 } else {
59 Self::Message(Box::new(x))
60 }
61 })
62 }
63}
64
65/// Represents a message.
66#[serde_with::skip_serializing_none]
67#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
68pub struct Message {
69 /// Chat the message belongs to.
70 pub chat: Chat,
71 /// Date the message was sent in Unix time.
72 pub date: Integer,
73 /// Date the message was last edited in Unix time.
74 pub edit_date: Option<Integer>,
75 /// Indicates whether the message can't be forwarded.
76 #[serde(default)]
77 pub has_protected_content: bool,
78 /// Unique message identifier inside the chat.
79 #[serde(rename = "message_id")]
80 pub id: Integer,
81 /// Indicates whether the message is a channel post that
82 /// was automatically forwarded
83 /// to the connected discussion group.
84 #[serde(default)]
85 pub is_automatic_forward: bool,
86 /// Sender of the message.
87 #[serde(flatten)]
88 pub sender: MessageSender,
89 /// Author signature.
90 pub author_signature: Option<String>,
91 /// Unique identifier of the business connection from which the message was received.
92 ///
93 /// If non-empty, the message belongs to a chat of the corresponding business account
94 /// that is independent from any potential bot chat which might share the same identifier.
95 pub business_connection_id: Option<String>,
96 /// Unique identifier of the message effect added to the message.
97 pub effect_id: Option<String>,
98 /// Information about the message that is being replied to, which may come from another chat or forum topic.
99 pub external_reply: Option<ExternalReplyInfo>,
100 /// formation about the original message for forwarded messages.
101 pub forward_origin: Option<MessageOrigin>,
102 /// Indicates whether the message media is covered by a spoiler animation.
103 pub has_media_spoiler: Option<bool>,
104 /// Whether the message was sent by an implicit action.
105 ///
106 /// For example, as an away or a greeting business message, or as a scheduled message.
107 pub is_from_offline: Option<bool>,
108 /// Indicates whether the message is sent to a forum topic.
109 pub is_topic_message: Option<bool>,
110 /// Options used for link preview generation for the message,
111 /// if it is a text message and link preview options were changed.
112 pub link_preview_options: Option<LinkPreviewOptions>,
113 /// Unique identifier of a media message group this message belongs to.
114 pub media_group_id: Option<String>,
115 /// Unique identifier of a message thread to which the message belongs;
116 /// for supergroups only.
117 pub message_thread_id: Option<Integer>,
118 /// The number of Telegram Stars that were paid by the sender of the message to send it.
119 pub paid_star_count: Option<Integer>,
120 /// For replies that quote part of the original message, the quoted part of the message.
121 pub quote: Option<TextQuote>,
122 /// Inline keyboard attached to the message.
123 pub reply_markup: Option<InlineKeyboardMarkup>,
124 /// For replies, the original message or story.
125 #[serde(flatten)]
126 pub reply_to: Option<ReplyTo>,
127 /// Number of boosts added by the user.
128 ///
129 /// Contains a value only if the sender of the message boosted the chat.
130 pub sender_boost_count: Option<Integer>,
131 /// The bot that actually sent the message on behalf of the business account.
132 ///
133 /// Available only for outgoing messages sent on behalf of the connected business account.
134 pub sender_business_bot: Option<User>,
135 /// Whether the caption must be shown above the message media.
136 pub show_caption_above_media: Option<bool>,
137 /// Bot through which the message was sent.
138 pub via_bot: Option<User>,
139
140 /// Contains message data.
141 #[serde(flatten)]
142 pub data: MessageData,
143}
144
145impl Message {
146 /// Creates a new `Message`.
147 ///
148 /// # Arguments
149 ///
150 /// * `id` - Unique message identifier inside the chat.
151 /// * `date` - Date the message was sent in Unix time.
152 /// * `chat` - Chat the message belongs to.
153 /// * `data` - Data of the message.
154 /// * `sender` - Sender of the message.
155 pub fn new<A, B>(id: Integer, date: Integer, chat: A, data: MessageData, sender: B) -> Self
156 where
157 A: Into<Chat>,
158 B: Into<MessageSender>,
159 {
160 Self {
161 chat: chat.into(),
162 data,
163 date,
164 edit_date: None,
165 has_protected_content: false,
166 id,
167 is_automatic_forward: false,
168 sender: sender.into(),
169 author_signature: None,
170 business_connection_id: None,
171 effect_id: None,
172 external_reply: None,
173 forward_origin: None,
174 has_media_spoiler: None,
175 is_from_offline: None,
176 is_topic_message: None,
177 link_preview_options: None,
178 media_group_id: None,
179 message_thread_id: None,
180 paid_star_count: None,
181 quote: None,
182 reply_markup: None,
183 reply_to: None,
184 sender_boost_count: None,
185 sender_business_bot: None,
186 show_caption_above_media: None,
187 via_bot: None,
188 }
189 }
190
191 /// Returns `true` if the message has edited and `false` otherwise.
192 pub fn is_edited(&self) -> bool {
193 self.edit_date.is_some()
194 }
195
196 /// Returns a text of the message (includes caption).
197 pub fn get_text(&self) -> Option<&Text> {
198 match self.data {
199 MessageData::Text(ref text)
200 | MessageData::Audio(MessageDataAudio {
201 caption: Some(ref text),
202 ..
203 })
204 | MessageData::Document(MessageDataDocument {
205 caption: Some(ref text),
206 ..
207 })
208 | MessageData::Photo(MessageDataPhoto {
209 caption: Some(ref text),
210 ..
211 })
212 | MessageData::Video(MessageDataVideo {
213 caption: Some(ref text),
214 ..
215 })
216 | MessageData::Voice(MessageDataVoice {
217 caption: Some(ref text),
218 ..
219 }) => Some(text),
220 _ => None,
221 }
222 }
223
224 /// Sets a new chat.
225 ///
226 /// # Arguments
227 ///
228 /// * `value` - Chat.
229 pub fn with_chat<T>(mut self, value: T) -> Self
230 where
231 T: Into<Chat>,
232 {
233 self.chat = value.into();
234 self
235 }
236
237 /// Sets a new data.
238 ///
239 /// # Arguments
240 ///
241 /// * `value` - Data of the message.
242 pub fn with_data(mut self, value: MessageData) -> Self {
243 self.data = value;
244 self
245 }
246
247 /// Sets a new date.
248 ///
249 /// # Arguments
250 ///
251 /// * `value` - Date; Unix timestamp.
252 pub fn with_date(mut self, value: Integer) -> Self {
253 self.date = value;
254 self
255 }
256
257 /// Sets a new edit date.
258 ///
259 /// # Arguments
260 ///
261 /// * `value` - Edit date; Unix timestamp.
262 pub fn with_edit_date(mut self, value: Integer) -> Self {
263 self.edit_date = Some(value);
264 self
265 }
266
267 /// Sets a new effect ID.
268 ///
269 /// # Arguments
270 ///
271 /// * `value` - Unique identifier of the message effect.
272 pub fn with_effect_id<T>(mut self, value: T) -> Self
273 where
274 T: Into<String>,
275 {
276 self.effect_id = Some(value.into());
277 self
278 }
279
280 /// Sets a new value for the `has_protected_content` flag.
281 ///
282 /// # Arguments
283 ///
284 /// * `value` - Indicates whether messages from the chat can't be forwarded to other chats.
285 pub fn with_has_protected_content(mut self, value: bool) -> Self {
286 self.has_protected_content = value;
287 self
288 }
289
290 /// Sets a new ID.
291 ///
292 /// # Arguments
293 ///
294 /// * `value` - Unique identifier inside a chat.
295 pub fn with_id(mut self, value: Integer) -> Self {
296 self.id = value;
297 self
298 }
299
300 /// Sets a new value for the `is_automatic_forward` flag.
301 ///
302 /// # Arguments
303 ///
304 /// * `value` - Indicates whether the message was automatically forwarded.
305 pub fn with_is_automatic_forward(mut self, value: bool) -> Self {
306 self.is_automatic_forward = value;
307 self
308 }
309
310 /// Sets a new sender.
311 ///
312 /// # Arguments
313 ///
314 /// * `value` - Sender.
315 pub fn with_sender<T>(mut self, value: T) -> Self
316 where
317 T: Into<MessageSender>,
318 {
319 self.sender = value.into();
320 self
321 }
322
323 /// Sets a new author signature.
324 ///
325 /// # Arguments
326 ///
327 /// * `value` - Author signature.
328 pub fn with_author_signature<T>(mut self, value: T) -> Self
329 where
330 T: Into<String>,
331 {
332 self.author_signature = Some(value.into());
333 self
334 }
335
336 /// Sets a new business connection ID.
337 ///
338 /// # Arguments
339 ///
340 /// * `value` - Unique identifier of the business connection from which the message was received.
341 pub fn with_business_connection_id<T>(mut self, value: T) -> Self
342 where
343 T: Into<String>,
344 {
345 self.business_connection_id = Some(value.into());
346 self
347 }
348
349 /// Sets a new external reply.
350 ///
351 /// # Arguments
352 ///
353 /// * `value` - Information about the message that is being replied to,
354 /// which may come from another chat or forum topic.
355 pub fn with_external_reply(mut self, value: ExternalReplyInfo) -> Self {
356 self.external_reply = Some(value);
357 self
358 }
359
360 /// Sets a new forward origin.
361 ///
362 /// # Arguments
363 ///
364 /// * `value` - Information about the message origin.
365 pub fn with_forward_origin(mut self, value: MessageOrigin) -> Self {
366 self.forward_origin = Some(value);
367 self
368 }
369
370 /// Sets a new value for the `has_media_spoiler` flag.
371 ///
372 /// # Arguments
373 ///
374 /// * `value` - Indicates whether the message has a media spoiler.
375 pub fn with_has_media_spoiler(mut self, value: bool) -> Self {
376 self.has_media_spoiler = Some(value);
377 self
378 }
379
380 /// Sets a new value for the `is_from_offline` flag.
381 ///
382 /// # Arguments
383 ///
384 /// * `value` - Indicates whether the message was sent by an implicit action.
385 pub fn with_is_from_offline(mut self, value: bool) -> Self {
386 self.is_from_offline = Some(value);
387 self
388 }
389
390 /// Sets a new value for the `is_topic_message` flag.
391 ///
392 /// # Arguments
393 ///
394 /// * `value` - Indicates whether the message is a topic message.
395 pub fn with_is_topic_message(mut self, value: bool) -> Self {
396 self.is_topic_message = Some(value);
397 self
398 }
399
400 /// Sets a new link preview options.
401 ///
402 /// # Arguments
403 ///
404 /// * `value` - New options.
405 pub fn with_link_preview_options(mut self, value: LinkPreviewOptions) -> Self {
406 self.link_preview_options = Some(value);
407 self
408 }
409
410 /// Sets a new media group ID.
411 ///
412 /// # Arguments
413 ///
414 /// * `value` - Media group ID.
415 pub fn with_media_group_id<T>(mut self, value: T) -> Self
416 where
417 T: Into<String>,
418 {
419 self.media_group_id = Some(value.into());
420 self
421 }
422
423 /// Sets a new message thread ID.
424 ///
425 /// # Arguments
426 ///
427 /// * `value` - Unique identifier of the target message thread;
428 /// supergroups only.
429 pub fn with_message_thread_id(mut self, value: Integer) -> Self {
430 self.message_thread_id = Some(value);
431 self
432 }
433
434 /// Sets a new paid star count
435 ///
436 /// # Arguments
437 ///
438 /// * `value` - The number of Telegram Stars that were paid by the sender of the message to send it.
439 pub fn with_paid_star_count(mut self, value: Integer) -> Self {
440 self.paid_star_count = Some(value);
441 self
442 }
443
444 /// Sets a new quote
445 ///
446 /// # Arguments
447 ///
448 /// * `value` - The quoted part of the original message.
449 pub fn with_quote(mut self, value: TextQuote) -> Self {
450 self.quote = Some(value);
451 self
452 }
453
454 /// Sets a new reply markup.
455 ///
456 /// # Arguments
457 ///
458 /// * `value` - Reply markup.
459 pub fn with_reply_markup<T>(mut self, value: T) -> Self
460 where
461 T: Into<InlineKeyboardMarkup>,
462 {
463 self.reply_markup = Some(value.into());
464 self
465 }
466
467 /// Sets a new original message or story for the reply.
468 ///
469 /// # Arguments
470 ///
471 /// * `value` - For replies, the original message or story.
472 pub fn with_reply_to<T>(mut self, value: T) -> Self
473 where
474 T: Into<ReplyTo>,
475 {
476 self.reply_to = Some(value.into());
477 self
478 }
479
480 /// Sets a new sender boost count.
481 ///
482 /// # Arguments
483 ///
484 /// * `value` - Number of boosts added by the user.
485 pub fn with_sender_boost_count(mut self, value: Integer) -> Self {
486 self.sender_boost_count = Some(value);
487 self
488 }
489
490 /// Sets a new bot.
491 ///
492 /// # Arguments
493 ///
494 /// * `value` - The bot that actually sent the message on behalf of the business account.
495 pub fn with_sender_business_bot(mut self, value: User) -> Self {
496 self.sender_business_bot = Some(value);
497 self
498 }
499
500 /// Sets a new value for the `show_caption_above_media` flag.
501 ///
502 /// # Arguments
503 ///
504 /// * `value` - Whether the caption must be shown above the message media.
505 pub fn with_show_caption_above_media(mut self, value: bool) -> Self {
506 self.show_caption_above_media = Some(value);
507 self
508 }
509
510 /// Sets a new bot.
511 ///
512 /// # Arguments
513 ///
514 /// * `value` - Bot through which the message was sent.
515 pub fn with_via_bot(mut self, value: User) -> Self {
516 self.via_bot = Some(value);
517 self
518 }
519}
520
521/// Represents an unique message identifier.
522#[derive(Copy, Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
523pub struct MessageId {
524 /// The unique message identifier.
525 pub message_id: Integer,
526}