Skip to main content

rustigram_types/
inline.rs

1use crate::chat::Location;
2use crate::user::User;
3use serde::{Deserialize, Serialize};
4
5/// An incoming inline query sent when a user types `@YourBot something` in any chat.
6///
7/// Respond with [`answerInlineQuery`](https://core.telegram.org/bots/api#answerinlinequery)
8/// within 10 seconds.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct InlineQuery {
11    /// Unique identifier for this query.
12    pub id: String,
13    /// The user who sent the query.
14    pub from: User,
15    /// Text of the query (up to 256 characters).
16    pub query: String,
17    /// Offset of the result to be returned.
18    pub offset: String,
19    /// Type of the chat from which the query was sent.
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub chat_type: Option<String>,
22    /// Sender's location, if the bot requests it.
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub location: Option<Location>,
25}
26
27/// The result a user chose from an inline query.
28///
29/// Delivered only when the bot has been granted access to inline feedback
30/// via [@BotFather](https://t.me/BotFather) under "Inline Feedback".
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct ChosenInlineResult {
33    /// Identifier of the chosen result.
34    pub result_id: String,
35    /// The user who chose the result.
36    pub from: User,
37    /// Sender's location, if the bot requests it.
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub location: Option<Location>,
40    /// Identifier of the sent inline message, if applicable.
41    #[serde(skip_serializing_if = "Option::is_none")]
42    pub inline_message_id: Option<String>,
43    /// The query used to obtain the result.
44    pub query: String,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(tag = "type", rename_all = "snake_case")]
49/// One result to show in an inline query answer.
50///
51/// Up to 50 results can be returned per [`answerInlineQuery`](https://core.telegram.org/bots/api#answerinlinequery) call.
52/// Each variant corresponds to a different content type (article, photo,
53/// video, etc.). Cached variants re-use a previously uploaded Telegram
54/// `file_id` rather than a URL.
55pub enum InlineQueryResult {
56    /// A link to an article or web page.
57    Article(InlineQueryResultArticle),
58    /// A link to a photo.
59    Photo(InlineQueryResultPhoto),
60    /// A link to an animated GIF.
61    Gif(InlineQueryResultGif),
62    /// A link to a video animation (MPEG4 without sound).
63    Mpeg4Gif(InlineQueryResultMpeg4Gif),
64    /// A link to a video.
65    Video(InlineQueryResultVideo),
66    /// A link to an audio file.
67    Audio(InlineQueryResultAudio),
68    /// A link to a voice recording.
69    Voice(InlineQueryResultVoice),
70    /// A link to a general file.
71    Document(InlineQueryResultDocument),
72    /// A geographic location.
73    Location(InlineQueryResultLocation),
74    /// A venue.
75    Venue(InlineQueryResultVenue),
76    /// A contact.
77    Contact(InlineQueryResultContact),
78    /// A game.
79    Game(InlineQueryResultGame),
80    /// A photo from a Telegram `file_id`.
81    CachedPhoto(InlineQueryResultCachedPhoto),
82    /// A GIF from a Telegram `file_id`.
83    CachedGif(InlineQueryResultCachedGif),
84    /// An MPEG4 GIF from a Telegram `file_id`.
85    CachedMpeg4Gif(InlineQueryResultCachedMpeg4Gif),
86    /// A sticker from a Telegram `file_id`.
87    CachedSticker(InlineQueryResultCachedSticker),
88    /// A document from a Telegram `file_id`.
89    CachedDocument(InlineQueryResultCachedDocument),
90    /// A video from a Telegram `file_id`.
91    CachedVideo(InlineQueryResultCachedVideo),
92    /// A voice message from a Telegram `file_id`.
93    CachedVoice(InlineQueryResultCachedVoice),
94    /// An audio file from a Telegram `file_id`.
95    CachedAudio(InlineQueryResultCachedAudio),
96}
97
98// ─── URL-based results ────────────────────────────────────────────────────────
99
100/// A link to an article or web page.
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct InlineQueryResultArticle {
103    /// Unique identifier for this result (1–64 bytes).
104    pub id: String,
105    /// Title of the result.
106    pub title: String,
107    /// Content of the message to be sent.
108    pub input_message_content: InputMessageContent,
109    /// Inline keyboard attached to the message.
110    #[serde(skip_serializing_if = "Option::is_none")]
111    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
112    /// URL of the result.
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub url: Option<String>,
115    /// Short description of the result.
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub description: Option<String>,
118    /// URL of the thumbnail for the result.
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub thumbnail_url: Option<String>,
121    /// Thumbnail width in pixels.
122    #[serde(skip_serializing_if = "Option::is_none")]
123    pub thumbnail_width: Option<u32>,
124    /// Thumbnail height in pixels.
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub thumbnail_height: Option<u32>,
127}
128
129/// A link to a photo (JPEG, max 5 MB).
130#[derive(Debug, Clone, Serialize, Deserialize)]
131/// A photo result in an inline query.
132pub struct InlineQueryResultPhoto {
133    /// Unique identifier for this result (1–64 bytes).
134    pub id: String,
135    /// A valid URL of the photo.
136    pub photo_url: String,
137    /// URL of the thumbnail for the photo.
138    pub thumbnail_url: String,
139    /// Photo width in pixels.
140    #[serde(skip_serializing_if = "Option::is_none")]
141    pub photo_width: Option<u32>,
142    /// Photo height in pixels.
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub photo_height: Option<u32>,
145    /// Title for the result.
146    #[serde(skip_serializing_if = "Option::is_none")]
147    pub title: Option<String>,
148    /// Short description of the result.
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub description: Option<String>,
151    /// Caption of the photo (0–1024 characters after entities parsing).
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub caption: Option<String>,
154    /// Parse mode for the caption. See [formatting options](https://core.telegram.org/bots/api#formatting-options) for more details.
155    #[serde(skip_serializing_if = "Option::is_none")]
156    pub parse_mode: Option<crate::message::ParseMode>,
157    /// Special entities in the caption; alternative to `parse_mode`.
158    #[serde(skip_serializing_if = "Option::is_none")]
159    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
160    /// `true` if the caption must be shown above the photo.
161    #[serde(skip_serializing_if = "Option::is_none")]
162    pub show_caption_above_media: Option<bool>,
163    /// Inline keyboard attached to the message.
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
166    /// Content of the message to be sent instead of the photo.
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub input_message_content: Option<InputMessageContent>,
169}
170
171/// A link to an animated GIF file (max 1 MB).
172#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct InlineQueryResultGif {
174    /// Unique identifier for this result (1–64 bytes).
175    pub id: String,
176    /// A valid URL for the GIF file.
177    pub gif_url: String,
178    /// URL of the static or animated thumbnail for the result.
179    pub thumbnail_url: String,
180    /// Width of the GIF in pixels.
181    #[serde(skip_serializing_if = "Option::is_none")]
182    pub gif_width: Option<u32>,
183    /// Height of the GIF in pixels.
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub gif_height: Option<u32>,
186    /// Duration of the GIF in seconds.
187    #[serde(skip_serializing_if = "Option::is_none")]
188    pub gif_duration: Option<u32>,
189    /// MIME type of the thumbnail (`image/jpeg`, `image/gif`, or `video/mp4`).
190    #[serde(skip_serializing_if = "Option::is_none")]
191    pub thumbnail_mime_type: Option<String>,
192    /// Title for the result.
193    #[serde(skip_serializing_if = "Option::is_none")]
194    pub title: Option<String>,
195    /// Caption of the GIF (0–1024 characters after entities parsing).
196    #[serde(skip_serializing_if = "Option::is_none")]
197    pub caption: Option<String>,
198    /// Parse mode for the caption. See [formatting options](https://core.telegram.org/bots/api#formatting-options) for more details.
199    #[serde(skip_serializing_if = "Option::is_none")]
200    pub parse_mode: Option<crate::message::ParseMode>,
201    /// Special entities in the caption; alternative to `parse_mode`.
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
204    /// `true` if the caption must be shown above the GIF.
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub show_caption_above_media: Option<bool>,
207    /// Inline keyboard attached to the message.
208    #[serde(skip_serializing_if = "Option::is_none")]
209    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
210    /// Content of the message to be sent instead of the GIF.
211    #[serde(skip_serializing_if = "Option::is_none")]
212    pub input_message_content: Option<InputMessageContent>,
213}
214
215/// A link to a video animation (MPEG4 without sound, max 1 MB).
216#[derive(Debug, Clone, Serialize, Deserialize)]
217pub struct InlineQueryResultMpeg4Gif {
218    /// Unique identifier for this result (1–64 bytes).
219    pub id: String,
220    /// A valid URL for the MPEG4 file.
221    pub mpeg4_url: String,
222    /// URL of the static or animated thumbnail.
223    pub thumbnail_url: String,
224    /// Video width in pixels.
225    #[serde(skip_serializing_if = "Option::is_none")]
226    pub mpeg4_width: Option<u32>,
227    /// Video height in pixels.
228    #[serde(skip_serializing_if = "Option::is_none")]
229    pub mpeg4_height: Option<u32>,
230    /// Video duration in seconds.
231    #[serde(skip_serializing_if = "Option::is_none")]
232    pub mpeg4_duration: Option<u32>,
233    /// MIME type of the thumbnail (`image/jpeg`, `image/gif`, or `video/mp4`).
234    #[serde(skip_serializing_if = "Option::is_none")]
235    pub thumbnail_mime_type: Option<String>,
236    /// Title for the result.
237    #[serde(skip_serializing_if = "Option::is_none")]
238    pub title: Option<String>,
239    /// Caption of the MPEG4 (0–1024 characters after entities parsing).
240    #[serde(skip_serializing_if = "Option::is_none")]
241    pub caption: Option<String>,
242    /// Parse mode for the caption.
243    #[serde(skip_serializing_if = "Option::is_none")]
244    pub parse_mode: Option<crate::message::ParseMode>,
245    /// Special entities in the caption; alternative to `parse_mode`.
246    #[serde(skip_serializing_if = "Option::is_none")]
247    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
248    /// `true` if the caption must be shown above the animation.
249    #[serde(skip_serializing_if = "Option::is_none")]
250    pub show_caption_above_media: Option<bool>,
251    /// Inline keyboard attached to the message.
252    #[serde(skip_serializing_if = "Option::is_none")]
253    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
254    /// Content of the message to be sent instead of the animation.
255    #[serde(skip_serializing_if = "Option::is_none")]
256    pub input_message_content: Option<InputMessageContent>,
257}
258
259/// A link to a video file (`text/html` or `video/mp4`).
260#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct InlineQueryResultVideo {
262    /// Unique identifier for this result (1–64 bytes).
263    pub id: String,
264    /// A valid URL for the video file.
265    pub video_url: String,
266    /// MIME type of the video (`text/html` or `video/mp4`).
267    pub mime_type: String,
268    /// URL of the thumbnail for the video.
269    pub thumbnail_url: String,
270    /// Title for the result.
271    pub title: String,
272    /// Caption of the video (0–1024 characters after entities parsing).
273    #[serde(skip_serializing_if = "Option::is_none")]
274    pub caption: Option<String>,
275    /// Parse mode for the caption.
276    #[serde(skip_serializing_if = "Option::is_none")]
277    pub parse_mode: Option<crate::message::ParseMode>,
278    /// Special entities in the caption; alternative to `parse_mode`.
279    #[serde(skip_serializing_if = "Option::is_none")]
280    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
281    /// `true` if the caption must be shown above the video.
282    #[serde(skip_serializing_if = "Option::is_none")]
283    pub show_caption_above_media: Option<bool>,
284    /// Video width in pixels.
285    #[serde(skip_serializing_if = "Option::is_none")]
286    pub video_width: Option<u32>,
287    /// Video height in pixels.
288    #[serde(skip_serializing_if = "Option::is_none")]
289    pub video_height: Option<u32>,
290    /// Video duration in seconds.
291    #[serde(skip_serializing_if = "Option::is_none")]
292    pub video_duration: Option<u32>,
293    /// Short description of the result.
294    #[serde(skip_serializing_if = "Option::is_none")]
295    pub description: Option<String>,
296    /// Inline keyboard attached to the message.
297    #[serde(skip_serializing_if = "Option::is_none")]
298    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
299    /// Content of the message to be sent instead of the video.
300    #[serde(skip_serializing_if = "Option::is_none")]
301    pub input_message_content: Option<InputMessageContent>,
302}
303
304/// A link to an audio file (`.mp3` or `.m4a`).
305#[derive(Debug, Clone, Serialize, Deserialize)]
306pub struct InlineQueryResultAudio {
307    /// Unique identifier for this result (1–64 bytes).
308    pub id: String,
309    /// A valid URL for the audio file.
310    pub audio_url: String,
311    /// Title.
312    pub title: String,
313    /// Caption of the audio (0–1024 characters after entities parsing).
314    #[serde(skip_serializing_if = "Option::is_none")]
315    pub caption: Option<String>,
316    /// Parse mode for the caption.
317    #[serde(skip_serializing_if = "Option::is_none")]
318    pub parse_mode: Option<crate::message::ParseMode>,
319    /// Special entities in the caption; alternative to `parse_mode`.
320    #[serde(skip_serializing_if = "Option::is_none")]
321    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
322    /// Performer of the audio.
323    #[serde(skip_serializing_if = "Option::is_none")]
324    pub performer: Option<String>,
325    /// Audio duration in seconds.
326    #[serde(skip_serializing_if = "Option::is_none")]
327    pub audio_duration: Option<u32>,
328    /// Inline keyboard attached to the message.
329    #[serde(skip_serializing_if = "Option::is_none")]
330    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
331    /// Content of the message to be sent instead of the audio.
332    #[serde(skip_serializing_if = "Option::is_none")]
333    pub input_message_content: Option<InputMessageContent>,
334}
335
336/// A link to a voice recording in `.ogg` format encoded with OPUS.
337#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct InlineQueryResultVoice {
339    /// Unique identifier for this result (1–64 bytes).
340    pub id: String,
341    /// A valid URL for the voice recording.
342    pub voice_url: String,
343    /// Recording title.
344    pub title: String,
345    /// Caption of the voice recording (0–1024 characters after entities parsing).
346    #[serde(skip_serializing_if = "Option::is_none")]
347    pub caption: Option<String>,
348    /// Parse mode for the caption.
349    #[serde(skip_serializing_if = "Option::is_none")]
350    pub parse_mode: Option<crate::message::ParseMode>,
351    /// Special entities in the caption; alternative to `parse_mode`.
352    #[serde(skip_serializing_if = "Option::is_none")]
353    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
354    /// Recording duration in seconds.
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub voice_duration: Option<u32>,
357    /// Inline keyboard attached to the message.
358    #[serde(skip_serializing_if = "Option::is_none")]
359    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
360    /// Content of the message to be sent instead of the voice recording.
361    #[serde(skip_serializing_if = "Option::is_none")]
362    pub input_message_content: Option<InputMessageContent>,
363}
364
365/// A link to a general file (`application/pdf` or `application/zip`).
366#[derive(Debug, Clone, Serialize, Deserialize)]
367pub struct InlineQueryResultDocument {
368    /// Unique identifier for this result (1–64 bytes).
369    pub id: String,
370    /// Title for the result.
371    pub title: String,
372    /// Caption of the document (0–1024 characters after entities parsing).
373    #[serde(skip_serializing_if = "Option::is_none")]
374    pub caption: Option<String>,
375    /// Parse mode for the caption.
376    #[serde(skip_serializing_if = "Option::is_none")]
377    pub parse_mode: Option<crate::message::ParseMode>,
378    /// Special entities in the caption; alternative to `parse_mode`.
379    #[serde(skip_serializing_if = "Option::is_none")]
380    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
381    /// A valid URL for the file.
382    pub document_url: String,
383    /// MIME type of the document (`application/pdf` or `application/zip`).
384    pub mime_type: String,
385    /// Short description of the result.
386    #[serde(skip_serializing_if = "Option::is_none")]
387    pub description: Option<String>,
388    /// Inline keyboard attached to the message.
389    #[serde(skip_serializing_if = "Option::is_none")]
390    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
391    /// Content of the message to be sent instead of the document.
392    #[serde(skip_serializing_if = "Option::is_none")]
393    pub input_message_content: Option<InputMessageContent>,
394    /// URL of the thumbnail for the result.
395    #[serde(skip_serializing_if = "Option::is_none")]
396    pub thumbnail_url: Option<String>,
397    /// Thumbnail width in pixels.
398    #[serde(skip_serializing_if = "Option::is_none")]
399    pub thumbnail_width: Option<u32>,
400    /// Thumbnail height in pixels.
401    #[serde(skip_serializing_if = "Option::is_none")]
402    pub thumbnail_height: Option<u32>,
403}
404
405/// A geographic location on a map.
406#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct InlineQueryResultLocation {
408    /// Unique identifier for this result (1–64 bytes).
409    pub id: String,
410    /// Location latitude in degrees.
411    pub latitude: f64,
412    /// Location longitude in degrees.
413    pub longitude: f64,
414    /// Location title.
415    pub title: String,
416    /// Radius of uncertainty for the location in metres (0–1500).
417    #[serde(skip_serializing_if = "Option::is_none")]
418    pub horizontal_accuracy: Option<f64>,
419    /// Period in seconds during which the location can be updated (60–86400).
420    #[serde(skip_serializing_if = "Option::is_none")]
421    pub live_period: Option<u32>,
422    /// Direction of movement in degrees (1–360) for live locations.
423    #[serde(skip_serializing_if = "Option::is_none")]
424    pub heading: Option<u16>,
425    /// Maximum distance in metres for proximity alerts about approaching another chat member.
426    #[serde(skip_serializing_if = "Option::is_none")]
427    pub proximity_alert_radius: Option<u32>,
428    /// Inline keyboard attached to the message.
429    #[serde(skip_serializing_if = "Option::is_none")]
430    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
431    /// Content of the message to be sent instead of the location.
432    #[serde(skip_serializing_if = "Option::is_none")]
433    pub input_message_content: Option<InputMessageContent>,
434    /// URL of the thumbnail for the result.
435    #[serde(skip_serializing_if = "Option::is_none")]
436    pub thumbnail_url: Option<String>,
437    /// Thumbnail width in pixels.
438    #[serde(skip_serializing_if = "Option::is_none")]
439    pub thumbnail_width: Option<u32>,
440    /// Thumbnail height in pixels.
441    #[serde(skip_serializing_if = "Option::is_none")]
442    pub thumbnail_height: Option<u32>,
443}
444
445/// A venue.
446#[derive(Debug, Clone, Serialize, Deserialize)]
447pub struct InlineQueryResultVenue {
448    /// Unique identifier for this result (1–64 bytes).
449    pub id: String,
450    /// Venue latitude in degrees.
451    pub latitude: f64,
452    /// Venue longitude in degrees.
453    pub longitude: f64,
454    /// Venue title.
455    pub title: String,
456    /// Venue address.
457    pub address: String,
458    /// Foursquare identifier of the venue.
459    #[serde(skip_serializing_if = "Option::is_none")]
460    pub foursquare_id: Option<String>,
461    /// Foursquare type of the venue.
462    #[serde(skip_serializing_if = "Option::is_none")]
463    pub foursquare_type: Option<String>,
464    /// Google Places identifier of the venue.
465    #[serde(skip_serializing_if = "Option::is_none")]
466    pub google_place_id: Option<String>,
467    /// Google Places type of the venue.
468    #[serde(skip_serializing_if = "Option::is_none")]
469    pub google_place_type: Option<String>,
470    /// Inline keyboard attached to the message.
471    #[serde(skip_serializing_if = "Option::is_none")]
472    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
473    /// Content of the message to be sent instead of the venue.
474    #[serde(skip_serializing_if = "Option::is_none")]
475    pub input_message_content: Option<InputMessageContent>,
476    /// URL of the thumbnail for the result.
477    #[serde(skip_serializing_if = "Option::is_none")]
478    pub thumbnail_url: Option<String>,
479    /// Thumbnail width in pixels.
480    #[serde(skip_serializing_if = "Option::is_none")]
481    pub thumbnail_width: Option<u32>,
482    /// Thumbnail height in pixels.
483    #[serde(skip_serializing_if = "Option::is_none")]
484    pub thumbnail_height: Option<u32>,
485}
486
487/// A contact with a phone number.
488#[derive(Debug, Clone, Serialize, Deserialize)]
489pub struct InlineQueryResultContact {
490    /// Unique identifier for this result (1–64 bytes).
491    pub id: String,
492    /// Contact phone number.
493    pub phone_number: String,
494    /// Contact first name.
495    pub first_name: String,
496    /// Contact last name.
497    #[serde(skip_serializing_if = "Option::is_none")]
498    pub last_name: Option<String>,
499    /// Contact vCard (0–2048 bytes).
500    #[serde(skip_serializing_if = "Option::is_none")]
501    pub vcard: Option<String>,
502    /// Inline keyboard attached to the message.
503    #[serde(skip_serializing_if = "Option::is_none")]
504    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
505    /// Content of the message to be sent instead of the contact.
506    #[serde(skip_serializing_if = "Option::is_none")]
507    pub input_message_content: Option<InputMessageContent>,
508    /// URL of the thumbnail for the result.
509    #[serde(skip_serializing_if = "Option::is_none")]
510    pub thumbnail_url: Option<String>,
511    /// Thumbnail width in pixels.
512    #[serde(skip_serializing_if = "Option::is_none")]
513    pub thumbnail_width: Option<u32>,
514    /// Thumbnail height in pixels.
515    #[serde(skip_serializing_if = "Option::is_none")]
516    pub thumbnail_height: Option<u32>,
517}
518
519/// A game result.
520#[derive(Debug, Clone, Serialize, Deserialize)]
521pub struct InlineQueryResultGame {
522    /// Unique identifier for this result (1–64 bytes).
523    pub id: String,
524    /// Short name of the game.
525    pub game_short_name: String,
526    /// Inline keyboard attached to the message.
527    #[serde(skip_serializing_if = "Option::is_none")]
528    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
529}
530
531// ─── Cached (file_id-based) results ──────────────────────────────────────────
532
533/// A photo from a previously uploaded Telegram file.
534#[derive(Debug, Clone, Serialize, Deserialize)]
535pub struct InlineQueryResultCachedPhoto {
536    /// Unique identifier for this result (1–64 bytes).
537    pub id: String,
538    /// A valid Telegram `file_id` of the photo.
539    pub photo_file_id: String,
540    /// Title for the result.
541    #[serde(skip_serializing_if = "Option::is_none")]
542    pub title: Option<String>,
543    /// Short description of the result.
544    #[serde(skip_serializing_if = "Option::is_none")]
545    pub description: Option<String>,
546    /// Caption of the photo (0–1024 characters after entities parsing).
547    #[serde(skip_serializing_if = "Option::is_none")]
548    pub caption: Option<String>,
549    /// Parse mode for the caption.
550    #[serde(skip_serializing_if = "Option::is_none")]
551    pub parse_mode: Option<crate::message::ParseMode>,
552    /// Special entities in the caption; alternative to `parse_mode`.
553    #[serde(skip_serializing_if = "Option::is_none")]
554    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
555    /// `true` if the caption must be shown above the photo.
556    #[serde(skip_serializing_if = "Option::is_none")]
557    pub show_caption_above_media: Option<bool>,
558    /// Inline keyboard attached to the message.
559    #[serde(skip_serializing_if = "Option::is_none")]
560    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
561    /// Content of the message to be sent instead of the photo.
562    #[serde(skip_serializing_if = "Option::is_none")]
563    pub input_message_content: Option<InputMessageContent>,
564}
565
566/// An animated GIF from a previously uploaded Telegram file.
567#[derive(Debug, Clone, Serialize, Deserialize)]
568pub struct InlineQueryResultCachedGif {
569    /// Unique identifier for this result (1–64 bytes).
570    pub id: String,
571    /// A valid Telegram `file_id` of the GIF.
572    pub gif_file_id: String,
573    /// Title for the result.
574    #[serde(skip_serializing_if = "Option::is_none")]
575    pub title: Option<String>,
576    /// Caption of the GIF (0–1024 characters after entities parsing).
577    #[serde(skip_serializing_if = "Option::is_none")]
578    pub caption: Option<String>,
579    /// Parse mode for the caption. See [formatting options](https://core.telegram.org/bots/api#formatting-options) for more details.
580    #[serde(skip_serializing_if = "Option::is_none")]
581    pub parse_mode: Option<crate::message::ParseMode>,
582    /// Special entities in the caption; alternative to `parse_mode`.
583    #[serde(skip_serializing_if = "Option::is_none")]
584    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
585    /// `true` if the caption must be shown above the GIF.
586    #[serde(skip_serializing_if = "Option::is_none")]
587    pub show_caption_above_media: Option<bool>,
588    /// Inline keyboard attached to the message.
589    #[serde(skip_serializing_if = "Option::is_none")]
590    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
591    /// Content of the message to be sent instead of the GIF.
592    #[serde(skip_serializing_if = "Option::is_none")]
593    pub input_message_content: Option<InputMessageContent>,
594}
595
596/// An MPEG4 animation from a previously uploaded Telegram file.
597#[derive(Debug, Clone, Serialize, Deserialize)]
598pub struct InlineQueryResultCachedMpeg4Gif {
599    /// Unique identifier for this result (1–64 bytes).
600    pub id: String,
601    /// A valid Telegram `file_id` of the MPEG4 animation.
602    pub mpeg4_file_id: String,
603    /// Title for the result.
604    #[serde(skip_serializing_if = "Option::is_none")]
605    pub title: Option<String>,
606    /// Caption of the animation (0–1024 characters after entities parsing).
607    #[serde(skip_serializing_if = "Option::is_none")]
608    pub caption: Option<String>,
609    /// Parse mode for the caption.
610    #[serde(skip_serializing_if = "Option::is_none")]
611    pub parse_mode: Option<crate::message::ParseMode>,
612    /// Special entities in the caption; alternative to `parse_mode`.
613    #[serde(skip_serializing_if = "Option::is_none")]
614    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
615    /// `true` if the caption must be shown above the animation.
616    #[serde(skip_serializing_if = "Option::is_none")]
617    pub show_caption_above_media: Option<bool>,
618    /// Inline keyboard attached to the message.
619    #[serde(skip_serializing_if = "Option::is_none")]
620    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
621    /// Content of the message to be sent instead of the animation.
622    #[serde(skip_serializing_if = "Option::is_none")]
623    pub input_message_content: Option<InputMessageContent>,
624}
625
626/// A sticker from a previously uploaded Telegram file.
627#[derive(Debug, Clone, Serialize, Deserialize)]
628pub struct InlineQueryResultCachedSticker {
629    /// Unique identifier for this result (1–64 bytes).
630    pub id: String,
631    /// A valid Telegram `file_id` of the sticker.
632    pub sticker_file_id: String,
633    /// Inline keyboard attached to the message.
634    #[serde(skip_serializing_if = "Option::is_none")]
635    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
636    /// Content of the message to be sent instead of the sticker.
637    #[serde(skip_serializing_if = "Option::is_none")]
638    pub input_message_content: Option<InputMessageContent>,
639}
640
641/// A document from a previously uploaded Telegram file.
642#[derive(Debug, Clone, Serialize, Deserialize)]
643pub struct InlineQueryResultCachedDocument {
644    /// Unique identifier for this result (1–64 bytes).
645    pub id: String,
646    /// Title for the result.
647    pub title: String,
648    /// A valid Telegram `file_id` of the document.
649    pub document_file_id: String,
650    /// Short description of the result.
651    #[serde(skip_serializing_if = "Option::is_none")]
652    pub description: Option<String>,
653    /// Caption of the document (0–1024 characters after entities parsing).
654    #[serde(skip_serializing_if = "Option::is_none")]
655    pub caption: Option<String>,
656    /// Parse mode for the caption.
657    #[serde(skip_serializing_if = "Option::is_none")]
658    pub parse_mode: Option<crate::message::ParseMode>,
659    /// Special entities in the caption; alternative to `parse_mode`.
660    #[serde(skip_serializing_if = "Option::is_none")]
661    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
662    /// Inline keyboard attached to the message.
663    #[serde(skip_serializing_if = "Option::is_none")]
664    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
665    /// Content of the message to be sent instead of the document.
666    #[serde(skip_serializing_if = "Option::is_none")]
667    pub input_message_content: Option<InputMessageContent>,
668}
669
670/// A video from a previously uploaded Telegram file.
671#[derive(Debug, Clone, Serialize, Deserialize)]
672pub struct InlineQueryResultCachedVideo {
673    /// Unique identifier for this result (1–64 bytes).
674    pub id: String,
675    /// A valid Telegram `file_id` of the video.
676    pub video_file_id: String,
677    /// Title for the result.
678    pub title: String,
679    /// Short description of the result.
680    #[serde(skip_serializing_if = "Option::is_none")]
681    pub description: Option<String>,
682    /// Caption of the video (0–1024 characters after entities parsing).
683    #[serde(skip_serializing_if = "Option::is_none")]
684    pub caption: Option<String>,
685    /// Parse mode for the caption.
686    #[serde(skip_serializing_if = "Option::is_none")]
687    pub parse_mode: Option<crate::message::ParseMode>,
688    /// Special entities in the caption; alternative to `parse_mode`.
689    #[serde(skip_serializing_if = "Option::is_none")]
690    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
691    /// `true` if the caption must be shown above the video.
692    #[serde(skip_serializing_if = "Option::is_none")]
693    pub show_caption_above_media: Option<bool>,
694    /// Inline keyboard attached to the message.
695    #[serde(skip_serializing_if = "Option::is_none")]
696    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
697    /// Content of the message to be sent instead of the video.
698    #[serde(skip_serializing_if = "Option::is_none")]
699    pub input_message_content: Option<InputMessageContent>,
700}
701
702/// A voice message from a previously uploaded Telegram file.
703#[derive(Debug, Clone, Serialize, Deserialize)]
704pub struct InlineQueryResultCachedVoice {
705    /// Unique identifier for this result (1–64 bytes).
706    pub id: String,
707    /// A valid Telegram `file_id` of the voice message.
708    pub voice_file_id: String,
709    /// Title for the result.
710    pub title: String,
711    /// Caption of the voice message (0–1024 characters after entities parsing).
712    #[serde(skip_serializing_if = "Option::is_none")]
713    pub caption: Option<String>,
714    /// Parse mode for the caption.
715    #[serde(skip_serializing_if = "Option::is_none")]
716    pub parse_mode: Option<crate::message::ParseMode>,
717    /// Special entities in the caption; alternative to `parse_mode`.
718    #[serde(skip_serializing_if = "Option::is_none")]
719    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
720    /// Inline keyboard attached to the message.
721    #[serde(skip_serializing_if = "Option::is_none")]
722    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
723    /// Content of the message to be sent instead of the voice message.
724    #[serde(skip_serializing_if = "Option::is_none")]
725    pub input_message_content: Option<InputMessageContent>,
726}
727
728/// An audio file from a previously uploaded Telegram file.
729#[derive(Debug, Clone, Serialize, Deserialize)]
730pub struct InlineQueryResultCachedAudio {
731    /// Unique identifier for this result (1–64 bytes).
732    pub id: String,
733    /// A valid Telegram `file_id` of the audio file.
734    pub audio_file_id: String,
735    /// Caption of the audio (0–1024 characters after entities parsing).
736    #[serde(skip_serializing_if = "Option::is_none")]
737    pub caption: Option<String>,
738    /// Parse mode for the caption.
739    #[serde(skip_serializing_if = "Option::is_none")]
740    pub parse_mode: Option<crate::message::ParseMode>,
741    /// Special entities in the caption; alternative to `parse_mode`.
742    #[serde(skip_serializing_if = "Option::is_none")]
743    pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
744    /// Inline keyboard attached to the message.
745    #[serde(skip_serializing_if = "Option::is_none")]
746    pub reply_markup: Option<crate::keyboard::InlineKeyboardMarkup>,
747    /// Content of the message to be sent instead of the audio.
748    #[serde(skip_serializing_if = "Option::is_none")]
749    pub input_message_content: Option<InputMessageContent>,
750}
751
752// ─── InputMessageContent ──────────────────────────────────────────────────────
753
754/// The content of a message to be sent as the result of an inline query.
755#[derive(Debug, Clone, Serialize, Deserialize)]
756#[serde(untagged)]
757/// The content of a message sent as the result of an inline query.
758pub enum InputMessageContent {
759    /// The message text.
760    Text(InputTextMessageContent),
761    /// A location on a map.
762    Location(InputLocationMessageContent),
763    /// A venue.
764    Venue(InputVenueMessageContent),
765    /// A contact.
766    Contact(InputContactMessageContent),
767    /// An invoice.
768    Invoice(InputInvoiceMessageContent),
769}
770
771/// A text message to send as an inline query result.
772#[derive(Debug, Clone, Serialize, Deserialize)]
773pub struct InputTextMessageContent {
774    /// Text of the message (1–4096 characters).
775    pub message_text: String,
776    /// Parse mode for the message text.
777    #[serde(skip_serializing_if = "Option::is_none")]
778    pub parse_mode: Option<crate::message::ParseMode>,
779    /// Special entities in the message text; alternative to `parse_mode`.
780    #[serde(skip_serializing_if = "Option::is_none")]
781    pub entities: Option<Vec<crate::message::MessageEntity>>,
782    /// Options for link preview generation.
783    #[serde(skip_serializing_if = "Option::is_none")]
784    pub link_preview_options: Option<crate::message::LinkPreviewOptions>,
785}
786
787/// A live location message to send as an inline query result.
788#[derive(Debug, Clone, Serialize, Deserialize)]
789pub struct InputLocationMessageContent {
790    /// Latitude in degrees.
791    pub latitude: f64,
792    /// Longitude in degrees.
793    pub longitude: f64,
794    /// Radius of uncertainty for the location in metres (0–1500).
795    #[serde(skip_serializing_if = "Option::is_none")]
796    pub horizontal_accuracy: Option<f64>,
797    /// Period in seconds during which the location can be updated (60–86400).
798    #[serde(skip_serializing_if = "Option::is_none")]
799    pub live_period: Option<u32>,
800    /// Direction of movement in degrees (1–360).
801    #[serde(skip_serializing_if = "Option::is_none")]
802    pub heading: Option<u16>,
803    /// Maximum distance in metres for proximity alerts.
804    #[serde(skip_serializing_if = "Option::is_none")]
805    pub proximity_alert_radius: Option<u32>,
806}
807
808/// A venue message to send as an inline query result.
809#[derive(Debug, Clone, Serialize, Deserialize)]
810pub struct InputVenueMessageContent {
811    /// Latitude in degrees.
812    pub latitude: f64,
813    /// Longitude in degrees.
814    pub longitude: f64,
815    /// Venue name.
816    pub title: String,
817    /// Venue address.
818    pub address: String,
819    /// Foursquare identifier of the venue.
820    #[serde(skip_serializing_if = "Option::is_none")]
821    pub foursquare_id: Option<String>,
822    /// Foursquare type of the venue.
823    #[serde(skip_serializing_if = "Option::is_none")]
824    pub foursquare_type: Option<String>,
825    /// Google Places identifier of the venue.
826    #[serde(skip_serializing_if = "Option::is_none")]
827    pub google_place_id: Option<String>,
828    /// Google Places type of the venue.
829    #[serde(skip_serializing_if = "Option::is_none")]
830    pub google_place_type: Option<String>,
831}
832
833/// A contact message to send as an inline query result.
834#[derive(Debug, Clone, Serialize, Deserialize)]
835pub struct InputContactMessageContent {
836    /// Contact phone number.
837    pub phone_number: String,
838    /// Contact first name.
839    pub first_name: String,
840    /// Contact last name.
841    #[serde(skip_serializing_if = "Option::is_none")]
842    pub last_name: Option<String>,
843    /// Contact vCard (0–2048 bytes).
844    #[serde(skip_serializing_if = "Option::is_none")]
845    pub vcard: Option<String>,
846}
847
848/// An invoice message to send as an inline query result.
849#[derive(Debug, Clone, Serialize, Deserialize)]
850pub struct InputInvoiceMessageContent {
851    /// Product name (1–32 characters).
852    pub title: String,
853    /// Product description (1–255 characters).
854    pub description: String,
855    /// Bot-defined invoice payload (1–128 bytes).
856    pub payload: String,
857    /// Payment provider token; not required for Telegram Stars.
858    #[serde(skip_serializing_if = "Option::is_none")]
859    pub provider_token: Option<String>,
860    /// Three-letter ISO 4217 currency code.
861    pub currency: String,
862    /// Price breakdown as a list of labeled portions.
863    pub prices: Vec<crate::payments::LabeledPrice>,
864    /// Maximum accepted tip amount in the smallest currency unit.
865    #[serde(skip_serializing_if = "Option::is_none")]
866    pub max_tip_amount: Option<u64>,
867    /// Suggested tip amounts in the smallest currency unit.
868    #[serde(skip_serializing_if = "Option::is_none")]
869    pub suggested_tip_amounts: Option<Vec<u64>>,
870    /// JSON-encoded data about the invoice for the payment provider.
871    #[serde(skip_serializing_if = "Option::is_none")]
872    pub provider_data: Option<String>,
873    /// URL of the product photo.
874    #[serde(skip_serializing_if = "Option::is_none")]
875    pub photo_url: Option<String>,
876    /// Photo size in bytes.
877    #[serde(skip_serializing_if = "Option::is_none")]
878    pub photo_size: Option<u64>,
879    /// Photo width in pixels.
880    #[serde(skip_serializing_if = "Option::is_none")]
881    pub photo_width: Option<u32>,
882    /// Photo height in pixels.
883    #[serde(skip_serializing_if = "Option::is_none")]
884    pub photo_height: Option<u32>,
885    /// Requests the buyer's full name.
886    #[serde(skip_serializing_if = "Option::is_none")]
887    pub need_name: Option<bool>,
888    /// Requests the buyer's phone number.
889    #[serde(skip_serializing_if = "Option::is_none")]
890    pub need_phone_number: Option<bool>,
891    /// Requests the buyer's email address.
892    #[serde(skip_serializing_if = "Option::is_none")]
893    pub need_email: Option<bool>,
894    /// Requests the buyer's shipping address.
895    #[serde(skip_serializing_if = "Option::is_none")]
896    pub need_shipping_address: Option<bool>,
897    /// Passes the buyer's phone number to the payment provider.
898    #[serde(skip_serializing_if = "Option::is_none")]
899    pub send_phone_number_to_provider: Option<bool>,
900    /// Passes the buyer's email address to the payment provider.
901    #[serde(skip_serializing_if = "Option::is_none")]
902    pub send_email_to_provider: Option<bool>,
903    /// `true` if the final price depends on the shipping method.
904    #[serde(skip_serializing_if = "Option::is_none")]
905    pub is_flexible: Option<bool>,
906}
907
908// ─── Misc ─────────────────────────────────────────────────────────────────────
909
910/// A message sent from a Web App on behalf of the user.
911#[derive(Debug, Clone, Serialize, Deserialize)]
912pub struct SentWebAppMessage {
913    /// Identifier of the sent inline message, if one was sent.
914    #[serde(skip_serializing_if = "Option::is_none")]
915    pub inline_message_id: Option<String>,
916}
917
918/// An inline message sent by a guest bot.
919///
920/// Returned by [`answerGuestQuery`](https://core.telegram.org/bots/api#answerguestquery).
921#[derive(Debug, Clone, Serialize, Deserialize)]
922pub struct SentGuestMessage {
923    /// Identifier of the sent inline message.
924    pub inline_message_id: String,
925}