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 InputMediaDocument {
424 pub media: String,
426 #[serde(skip_serializing_if = "Option::is_none")]
428 pub thumbnail: Option<String>,
429 #[serde(skip_serializing_if = "Option::is_none")]
431 pub caption: Option<String>,
432 #[serde(skip_serializing_if = "Option::is_none")]
434 pub parse_mode: Option<crate::message::ParseMode>,
435 #[serde(skip_serializing_if = "Option::is_none")]
437 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
438 #[serde(skip_serializing_if = "Option::is_none")]
440 pub disable_content_type_detection: Option<bool>,
441}
442
443#[derive(Debug, Clone, Serialize, Deserialize)]
447pub struct InputMediaLivePhoto {
448 pub media: String,
450 pub photo: String,
452 #[serde(skip_serializing_if = "Option::is_none")]
454 pub caption: Option<String>,
455 #[serde(skip_serializing_if = "Option::is_none")]
457 pub parse_mode: Option<crate::message::ParseMode>,
458 #[serde(skip_serializing_if = "Option::is_none")]
460 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
461 #[serde(skip_serializing_if = "Option::is_none")]
463 pub show_caption_above_media: Option<bool>,
464 #[serde(skip_serializing_if = "Option::is_none")]
466 pub has_spoiler: Option<bool>,
467}
468
469#[derive(Debug, Clone, Serialize, Deserialize)]
471pub struct InputMediaLocation {
472 pub latitude: f64,
474 pub longitude: f64,
476 #[serde(skip_serializing_if = "Option::is_none")]
478 pub horizontal_accuracy: Option<f64>,
479}
480
481#[derive(Debug, Clone, Serialize, Deserialize)]
483pub struct InputMediaVenue {
484 pub latitude: f64,
486 pub longitude: f64,
488 pub title: String,
490 pub address: String,
492 #[serde(skip_serializing_if = "Option::is_none")]
494 pub foursquare_id: Option<String>,
495 #[serde(skip_serializing_if = "Option::is_none")]
497 pub foursquare_type: Option<String>,
498 #[serde(skip_serializing_if = "Option::is_none")]
500 pub google_place_id: Option<String>,
501 #[serde(skip_serializing_if = "Option::is_none")]
503 pub google_place_type: Option<String>,
504}
505
506#[derive(Debug, Clone, Serialize, Deserialize)]
508pub struct InputMediaSticker {
509 pub media: String,
511 #[serde(skip_serializing_if = "Option::is_none")]
513 pub emoji: Option<String>,
514}
515
516#[derive(Debug, Clone, Serialize, Deserialize)]
522#[serde(tag = "type", rename_all = "snake_case")]
523pub enum InputMedia {
524 Photo(InputMediaPhoto),
526 Video(InputMediaVideo),
528 Animation(InputMediaAnimation),
530 Audio(InputMediaAudio),
532 Document(InputMediaDocument),
534 LivePhoto(InputMediaLivePhoto),
536}
537
538#[derive(Debug, Clone, Serialize, Deserialize)]
542pub struct InputPaidMediaPhoto {
543 pub media: String,
545}
546
547#[derive(Debug, Clone, Serialize, Deserialize)]
549pub struct InputPaidMediaVideo {
550 pub media: String,
552 #[serde(skip_serializing_if = "Option::is_none")]
554 pub thumbnail: Option<String>,
555 #[serde(skip_serializing_if = "Option::is_none")]
557 pub cover: Option<String>,
558 #[serde(skip_serializing_if = "Option::is_none")]
560 pub start_timestamp: Option<i64>,
561 #[serde(skip_serializing_if = "Option::is_none")]
563 pub width: Option<u32>,
564 #[serde(skip_serializing_if = "Option::is_none")]
566 pub height: Option<u32>,
567 #[serde(skip_serializing_if = "Option::is_none")]
569 pub duration: Option<u32>,
570 #[serde(skip_serializing_if = "Option::is_none")]
572 pub supports_streaming: Option<bool>,
573}
574
575#[derive(Debug, Clone, Serialize, Deserialize)]
580pub struct InputPaidMediaLivePhoto {
581 pub media: String,
583 pub photo: String,
585}
586
587#[derive(Debug, Clone, Serialize, Deserialize)]
592#[serde(tag = "type", rename_all = "snake_case")]
593pub enum InputPaidMedia {
594 Photo(InputPaidMediaPhoto),
596 Video(InputPaidMediaVideo),
598 LivePhoto(InputPaidMediaLivePhoto),
600}
601
602#[derive(Debug, Clone, Serialize, Deserialize)]
606pub struct InputProfilePhotoStatic {
607 pub photo: String,
612}
613
614#[derive(Debug, Clone, Serialize, Deserialize)]
616pub struct InputProfilePhotoAnimated {
617 pub animation: String,
622 #[serde(skip_serializing_if = "Option::is_none")]
625 pub main_frame_timestamp: Option<f64>,
626}
627
628#[derive(Debug, Clone, Serialize, Deserialize)]
632#[serde(tag = "type", rename_all = "snake_case")]
633pub enum InputProfilePhoto {
634 Static(InputProfilePhotoStatic),
636 Animated(InputProfilePhotoAnimated),
638}