1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct PhotoSize {
6 pub file_id: String,
8 pub file_unique_id: String,
10 pub width: u32,
12 pub height: u32,
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub file_size: Option<u64>,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct File {
22 pub file_id: String,
24 pub file_unique_id: String,
26 #[serde(skip_serializing_if = "Option::is_none")]
28 pub file_size: Option<u64>,
29 #[serde(skip_serializing_if = "Option::is_none")]
31 pub file_path: Option<String>,
32}
33
34impl File {
35 #[must_use]
37 pub fn url(&self, token: &str) -> Option<String> {
38 self.file_path
39 .as_ref()
40 .map(|path| format!("https://api.telegram.org/file/bot{token}/{path}"))
41 }
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct Audio {
47 pub file_id: String,
49 pub file_unique_id: String,
51 pub duration: u32,
53 #[serde(skip_serializing_if = "Option::is_none")]
55 pub performer: Option<String>,
56 #[serde(skip_serializing_if = "Option::is_none")]
58 pub title: Option<String>,
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub file_name: Option<String>,
62 #[serde(skip_serializing_if = "Option::is_none")]
64 pub mime_type: Option<String>,
65 #[serde(skip_serializing_if = "Option::is_none")]
67 pub file_size: Option<u64>,
68 #[serde(skip_serializing_if = "Option::is_none")]
70 pub thumbnail: Option<PhotoSize>,
71}
72
73#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct Document {
76 pub file_id: String,
78 pub file_unique_id: String,
80 #[serde(skip_serializing_if = "Option::is_none")]
82 pub thumbnail: Option<PhotoSize>,
83 #[serde(skip_serializing_if = "Option::is_none")]
85 pub file_name: Option<String>,
86 #[serde(skip_serializing_if = "Option::is_none")]
88 pub mime_type: Option<String>,
89 #[serde(skip_serializing_if = "Option::is_none")]
91 pub file_size: Option<u64>,
92}
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
98pub struct VideoQuality {
99 pub file_id: String,
101 pub file_unique_id: String,
103 pub width: u32,
105 pub height: u32,
107 pub codec: String,
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pub file_size: Option<u64>,
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct Video {
117 pub file_id: String,
119 pub file_unique_id: String,
121 pub width: u32,
123 pub height: u32,
125 pub duration: u32,
127 #[serde(skip_serializing_if = "Option::is_none")]
129 pub thumbnail: Option<PhotoSize>,
130 #[serde(skip_serializing_if = "Option::is_none")]
132 pub cover: Option<Vec<PhotoSize>>,
133 #[serde(skip_serializing_if = "Option::is_none")]
135 pub start_timestamp: Option<u32>,
136 #[serde(skip_serializing_if = "Option::is_none")]
138 pub qualities: Option<Vec<VideoQuality>>,
139 #[serde(skip_serializing_if = "Option::is_none")]
141 pub file_name: Option<String>,
142 #[serde(skip_serializing_if = "Option::is_none")]
144 pub mime_type: Option<String>,
145 #[serde(skip_serializing_if = "Option::is_none")]
147 pub file_size: Option<u64>,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct Animation {
153 pub file_id: String,
155 pub file_unique_id: String,
157 pub width: u32,
159 pub height: u32,
161 pub duration: u32,
163 #[serde(skip_serializing_if = "Option::is_none")]
165 pub thumbnail: Option<PhotoSize>,
166 #[serde(skip_serializing_if = "Option::is_none")]
168 pub file_name: Option<String>,
169 #[serde(skip_serializing_if = "Option::is_none")]
171 pub mime_type: Option<String>,
172 #[serde(skip_serializing_if = "Option::is_none")]
174 pub file_size: Option<u64>,
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
179pub struct Voice {
180 pub file_id: String,
182 pub file_unique_id: String,
184 pub duration: u32,
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub mime_type: Option<String>,
189 #[serde(skip_serializing_if = "Option::is_none")]
191 pub file_size: Option<u64>,
192}
193
194#[derive(Debug, Clone, Serialize, Deserialize)]
196pub struct VideoNote {
197 pub file_id: String,
199 pub file_unique_id: String,
201 pub length: u32,
203 pub duration: u32,
205 #[serde(skip_serializing_if = "Option::is_none")]
207 pub thumbnail: Option<PhotoSize>,
208 #[serde(skip_serializing_if = "Option::is_none")]
210 pub file_size: Option<u64>,
211}
212
213#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct LivePhoto {
216 #[serde(skip_serializing_if = "Option::is_none")]
218 pub photo: Option<Vec<PhotoSize>>,
219 pub file_id: String,
221 pub file_unique_id: String,
223 pub width: u32,
225 pub height: u32,
227 pub duration: u32,
229 #[serde(skip_serializing_if = "Option::is_none")]
231 pub mime_type: Option<String>,
232 #[serde(skip_serializing_if = "Option::is_none")]
234 pub file_size: Option<u64>,
235}
236
237#[derive(Debug, Clone)]
239pub enum InputFile {
240 FileId(String),
242 Url(String),
244 Bytes {
246 filename: String,
248 data: Vec<u8>,
250 mime_type: String,
252 },
253 Attach(String),
255}
256
257impl InputFile {
258 #[must_use]
260 pub fn as_str(&self) -> &str {
261 match self {
262 Self::FileId(id) => id,
263 Self::Url(url) => url,
264 Self::Attach(name) => name,
265 Self::Bytes { filename, .. } => filename,
266 }
267 }
268
269 #[must_use]
271 pub fn requires_multipart(&self) -> bool {
272 matches!(self, Self::Bytes { .. })
273 }
274}
275
276#[derive(Debug, Clone, Serialize, Deserialize)]
278pub struct PassportFile {
279 pub file_id: String,
281 pub file_unique_id: String,
283 pub file_size: u64,
285 pub file_date: i64,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
296pub struct InputMediaPhoto {
297 pub media: String,
299 #[serde(skip_serializing_if = "Option::is_none")]
301 pub caption: Option<String>,
302 #[serde(skip_serializing_if = "Option::is_none")]
304 pub parse_mode: Option<crate::message::ParseMode>,
305 #[serde(skip_serializing_if = "Option::is_none")]
307 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
308 #[serde(skip_serializing_if = "Option::is_none")]
310 pub show_caption_above_media: Option<bool>,
311 #[serde(skip_serializing_if = "Option::is_none")]
313 pub has_spoiler: Option<bool>,
314}
315
316#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct InputMediaVideo {
319 pub media: String,
321 #[serde(skip_serializing_if = "Option::is_none")]
323 pub thumbnail: Option<String>,
324 #[serde(skip_serializing_if = "Option::is_none")]
326 pub cover: Option<String>,
327 #[serde(skip_serializing_if = "Option::is_none")]
329 pub start_timestamp: Option<i64>,
330 #[serde(skip_serializing_if = "Option::is_none")]
332 pub caption: Option<String>,
333 #[serde(skip_serializing_if = "Option::is_none")]
335 pub parse_mode: Option<crate::message::ParseMode>,
336 #[serde(skip_serializing_if = "Option::is_none")]
338 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
339 #[serde(skip_serializing_if = "Option::is_none")]
341 pub show_caption_above_media: Option<bool>,
342 #[serde(skip_serializing_if = "Option::is_none")]
344 pub width: Option<u32>,
345 #[serde(skip_serializing_if = "Option::is_none")]
347 pub height: Option<u32>,
348 #[serde(skip_serializing_if = "Option::is_none")]
350 pub duration: Option<u32>,
351 #[serde(skip_serializing_if = "Option::is_none")]
353 pub supports_streaming: Option<bool>,
354 #[serde(skip_serializing_if = "Option::is_none")]
356 pub has_spoiler: Option<bool>,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize)]
361pub struct InputMediaAnimation {
362 pub media: String,
364 #[serde(skip_serializing_if = "Option::is_none")]
366 pub thumbnail: Option<String>,
367 #[serde(skip_serializing_if = "Option::is_none")]
369 pub caption: Option<String>,
370 #[serde(skip_serializing_if = "Option::is_none")]
372 pub parse_mode: Option<crate::message::ParseMode>,
373 #[serde(skip_serializing_if = "Option::is_none")]
375 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
376 #[serde(skip_serializing_if = "Option::is_none")]
378 pub show_caption_above_media: Option<bool>,
379 #[serde(skip_serializing_if = "Option::is_none")]
381 pub width: Option<u32>,
382 #[serde(skip_serializing_if = "Option::is_none")]
384 pub height: Option<u32>,
385 #[serde(skip_serializing_if = "Option::is_none")]
387 pub duration: Option<u32>,
388 #[serde(skip_serializing_if = "Option::is_none")]
390 pub has_spoiler: Option<bool>,
391}
392
393#[derive(Debug, Clone, Serialize, Deserialize)]
395pub struct InputMediaAudio {
396 pub media: String,
398 #[serde(skip_serializing_if = "Option::is_none")]
400 pub thumbnail: Option<String>,
401 #[serde(skip_serializing_if = "Option::is_none")]
403 pub caption: Option<String>,
404 #[serde(skip_serializing_if = "Option::is_none")]
406 pub parse_mode: Option<crate::message::ParseMode>,
407 #[serde(skip_serializing_if = "Option::is_none")]
409 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
410 #[serde(skip_serializing_if = "Option::is_none")]
412 pub duration: Option<u32>,
413 #[serde(skip_serializing_if = "Option::is_none")]
415 pub performer: Option<String>,
416 #[serde(skip_serializing_if = "Option::is_none")]
418 pub title: Option<String>,
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
423pub struct InputMediaVoiceNote {
424 pub media: String,
426 #[serde(skip_serializing_if = "Option::is_none")]
428 pub caption: Option<String>,
429 #[serde(skip_serializing_if = "Option::is_none")]
431 pub parse_mode: Option<crate::message::ParseMode>,
432 #[serde(skip_serializing_if = "Option::is_none")]
434 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
435 #[serde(skip_serializing_if = "Option::is_none")]
437 pub duration: Option<u32>,
438}
439
440#[derive(Debug, Clone, Serialize, Deserialize)]
442pub struct InputMediaDocument {
443 pub media: String,
445 #[serde(skip_serializing_if = "Option::is_none")]
447 pub thumbnail: Option<String>,
448 #[serde(skip_serializing_if = "Option::is_none")]
450 pub caption: Option<String>,
451 #[serde(skip_serializing_if = "Option::is_none")]
453 pub parse_mode: Option<crate::message::ParseMode>,
454 #[serde(skip_serializing_if = "Option::is_none")]
456 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
457 #[serde(skip_serializing_if = "Option::is_none")]
459 pub disable_content_type_detection: Option<bool>,
460}
461
462#[derive(Debug, Clone, Serialize, Deserialize)]
466pub struct InputMediaLivePhoto {
467 pub media: String,
469 pub photo: String,
471 #[serde(skip_serializing_if = "Option::is_none")]
473 pub caption: Option<String>,
474 #[serde(skip_serializing_if = "Option::is_none")]
476 pub parse_mode: Option<crate::message::ParseMode>,
477 #[serde(skip_serializing_if = "Option::is_none")]
479 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
480 #[serde(skip_serializing_if = "Option::is_none")]
482 pub show_caption_above_media: Option<bool>,
483 #[serde(skip_serializing_if = "Option::is_none")]
485 pub has_spoiler: Option<bool>,
486}
487
488#[derive(Debug, Clone, Serialize, Deserialize)]
490pub struct InputMediaLocation {
491 pub latitude: f64,
493 pub longitude: f64,
495 #[serde(skip_serializing_if = "Option::is_none")]
497 pub horizontal_accuracy: Option<f64>,
498}
499
500#[derive(Debug, Clone, Serialize, Deserialize)]
502pub struct InputMediaVenue {
503 pub latitude: f64,
505 pub longitude: f64,
507 pub title: String,
509 pub address: String,
511 #[serde(skip_serializing_if = "Option::is_none")]
513 pub foursquare_id: Option<String>,
514 #[serde(skip_serializing_if = "Option::is_none")]
516 pub foursquare_type: Option<String>,
517 #[serde(skip_serializing_if = "Option::is_none")]
519 pub google_place_id: Option<String>,
520 #[serde(skip_serializing_if = "Option::is_none")]
522 pub google_place_type: Option<String>,
523}
524
525#[derive(Debug, Clone, Serialize, Deserialize)]
527pub struct InputMediaSticker {
528 pub media: String,
530 #[serde(skip_serializing_if = "Option::is_none")]
532 pub emoji: Option<String>,
533}
534
535#[derive(Debug, Clone, Serialize, Deserialize)]
541#[serde(tag = "type", rename_all = "snake_case")]
542pub enum InputMedia {
543 Photo(InputMediaPhoto),
545 Video(InputMediaVideo),
547 Animation(InputMediaAnimation),
549 Audio(InputMediaAudio),
551 Document(InputMediaDocument),
553 LivePhoto(InputMediaLivePhoto),
555 VoiceNote(InputMediaVoiceNote),
557}
558
559#[derive(Debug, Clone, Serialize, Deserialize)]
563pub struct InputPaidMediaPhoto {
564 pub media: String,
566}
567
568#[derive(Debug, Clone, Serialize, Deserialize)]
570pub struct InputPaidMediaVideo {
571 pub media: String,
573 #[serde(skip_serializing_if = "Option::is_none")]
575 pub thumbnail: Option<String>,
576 #[serde(skip_serializing_if = "Option::is_none")]
578 pub cover: Option<String>,
579 #[serde(skip_serializing_if = "Option::is_none")]
581 pub start_timestamp: Option<i64>,
582 #[serde(skip_serializing_if = "Option::is_none")]
584 pub width: Option<u32>,
585 #[serde(skip_serializing_if = "Option::is_none")]
587 pub height: Option<u32>,
588 #[serde(skip_serializing_if = "Option::is_none")]
590 pub duration: Option<u32>,
591 #[serde(skip_serializing_if = "Option::is_none")]
593 pub supports_streaming: Option<bool>,
594}
595
596#[derive(Debug, Clone, Serialize, Deserialize)]
601pub struct InputPaidMediaLivePhoto {
602 pub media: String,
604 pub photo: String,
606}
607
608#[derive(Debug, Clone, Serialize, Deserialize)]
613#[serde(tag = "type", rename_all = "snake_case")]
614pub enum InputPaidMedia {
615 Photo(InputPaidMediaPhoto),
617 Video(InputPaidMediaVideo),
619 LivePhoto(InputPaidMediaLivePhoto),
621}
622
623#[derive(Debug, Clone, Serialize, Deserialize)]
627pub struct InputProfilePhotoStatic {
628 pub photo: String,
633}
634
635#[derive(Debug, Clone, Serialize, Deserialize)]
637pub struct InputProfilePhotoAnimated {
638 pub animation: String,
643 #[serde(skip_serializing_if = "Option::is_none")]
646 pub main_frame_timestamp: Option<f64>,
647}
648
649#[derive(Debug, Clone, Serialize, Deserialize)]
653#[serde(tag = "type", rename_all = "snake_case")]
654pub enum InputProfilePhoto {
655 Static(InputProfilePhotoStatic),
657 Animated(InputProfilePhotoAnimated),
659}