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)]
215pub enum InputFile {
216 FileId(String),
218 Url(String),
220 Bytes {
222 filename: String,
224 data: Vec<u8>,
226 mime_type: String,
228 },
229 Attach(String),
231}
232
233impl InputFile {
234 #[must_use]
236 pub fn as_str(&self) -> &str {
237 match self {
238 Self::FileId(id) => id,
239 Self::Url(url) => url,
240 Self::Attach(name) => name,
241 Self::Bytes { filename, .. } => filename,
242 }
243 }
244
245 #[must_use]
247 pub fn requires_multipart(&self) -> bool {
248 matches!(self, Self::Bytes { .. })
249 }
250}
251
252#[derive(Debug, Clone, Serialize, Deserialize)]
254pub struct PassportFile {
255 pub file_id: String,
257 pub file_unique_id: String,
259 pub file_size: u64,
261 pub file_date: i64,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize)]
272pub struct InputMediaPhoto {
273 pub media: String,
275 #[serde(skip_serializing_if = "Option::is_none")]
277 pub caption: Option<String>,
278 #[serde(skip_serializing_if = "Option::is_none")]
280 pub parse_mode: Option<crate::message::ParseMode>,
281 #[serde(skip_serializing_if = "Option::is_none")]
283 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
284 #[serde(skip_serializing_if = "Option::is_none")]
286 pub show_caption_above_media: Option<bool>,
287 #[serde(skip_serializing_if = "Option::is_none")]
289 pub has_spoiler: Option<bool>,
290}
291
292#[derive(Debug, Clone, Serialize, Deserialize)]
294pub struct InputMediaVideo {
295 pub media: String,
297 #[serde(skip_serializing_if = "Option::is_none")]
299 pub thumbnail: Option<String>,
300 #[serde(skip_serializing_if = "Option::is_none")]
302 pub cover: Option<String>,
303 #[serde(skip_serializing_if = "Option::is_none")]
305 pub start_timestamp: Option<i64>,
306 #[serde(skip_serializing_if = "Option::is_none")]
308 pub caption: Option<String>,
309 #[serde(skip_serializing_if = "Option::is_none")]
311 pub parse_mode: Option<crate::message::ParseMode>,
312 #[serde(skip_serializing_if = "Option::is_none")]
314 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
315 #[serde(skip_serializing_if = "Option::is_none")]
317 pub show_caption_above_media: Option<bool>,
318 #[serde(skip_serializing_if = "Option::is_none")]
320 pub width: Option<u32>,
321 #[serde(skip_serializing_if = "Option::is_none")]
323 pub height: Option<u32>,
324 #[serde(skip_serializing_if = "Option::is_none")]
326 pub duration: Option<u32>,
327 #[serde(skip_serializing_if = "Option::is_none")]
329 pub supports_streaming: Option<bool>,
330 #[serde(skip_serializing_if = "Option::is_none")]
332 pub has_spoiler: Option<bool>,
333}
334
335#[derive(Debug, Clone, Serialize, Deserialize)]
337pub struct InputMediaAnimation {
338 pub media: String,
340 #[serde(skip_serializing_if = "Option::is_none")]
342 pub thumbnail: Option<String>,
343 #[serde(skip_serializing_if = "Option::is_none")]
345 pub caption: Option<String>,
346 #[serde(skip_serializing_if = "Option::is_none")]
348 pub parse_mode: Option<crate::message::ParseMode>,
349 #[serde(skip_serializing_if = "Option::is_none")]
351 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
352 #[serde(skip_serializing_if = "Option::is_none")]
354 pub show_caption_above_media: Option<bool>,
355 #[serde(skip_serializing_if = "Option::is_none")]
357 pub width: Option<u32>,
358 #[serde(skip_serializing_if = "Option::is_none")]
360 pub height: Option<u32>,
361 #[serde(skip_serializing_if = "Option::is_none")]
363 pub duration: Option<u32>,
364 #[serde(skip_serializing_if = "Option::is_none")]
366 pub has_spoiler: Option<bool>,
367}
368
369#[derive(Debug, Clone, Serialize, Deserialize)]
371pub struct InputMediaAudio {
372 pub media: String,
374 #[serde(skip_serializing_if = "Option::is_none")]
376 pub thumbnail: Option<String>,
377 #[serde(skip_serializing_if = "Option::is_none")]
379 pub caption: Option<String>,
380 #[serde(skip_serializing_if = "Option::is_none")]
382 pub parse_mode: Option<crate::message::ParseMode>,
383 #[serde(skip_serializing_if = "Option::is_none")]
385 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
386 #[serde(skip_serializing_if = "Option::is_none")]
388 pub duration: Option<u32>,
389 #[serde(skip_serializing_if = "Option::is_none")]
391 pub performer: Option<String>,
392 #[serde(skip_serializing_if = "Option::is_none")]
394 pub title: Option<String>,
395}
396
397#[derive(Debug, Clone, Serialize, Deserialize)]
399pub struct InputMediaDocument {
400 pub media: String,
402 #[serde(skip_serializing_if = "Option::is_none")]
404 pub thumbnail: Option<String>,
405 #[serde(skip_serializing_if = "Option::is_none")]
407 pub caption: Option<String>,
408 #[serde(skip_serializing_if = "Option::is_none")]
410 pub parse_mode: Option<crate::message::ParseMode>,
411 #[serde(skip_serializing_if = "Option::is_none")]
413 pub caption_entities: Option<Vec<crate::message::MessageEntity>>,
414 #[serde(skip_serializing_if = "Option::is_none")]
416 pub disable_content_type_detection: Option<bool>,
417}
418
419#[derive(Debug, Clone, Serialize, Deserialize)]
425#[serde(tag = "type", rename_all = "snake_case")]
426pub enum InputMedia {
427 Photo(InputMediaPhoto),
429 Video(InputMediaVideo),
431 Animation(InputMediaAnimation),
433 Audio(InputMediaAudio),
435 Document(InputMediaDocument),
437}
438
439#[derive(Debug, Clone, Serialize, Deserialize)]
443pub struct InputPaidMediaPhoto {
444 pub media: String,
446}
447
448#[derive(Debug, Clone, Serialize, Deserialize)]
450pub struct InputPaidMediaVideo {
451 pub media: String,
453 #[serde(skip_serializing_if = "Option::is_none")]
455 pub thumbnail: Option<String>,
456 #[serde(skip_serializing_if = "Option::is_none")]
458 pub cover: Option<String>,
459 #[serde(skip_serializing_if = "Option::is_none")]
461 pub start_timestamp: Option<i64>,
462 #[serde(skip_serializing_if = "Option::is_none")]
464 pub width: Option<u32>,
465 #[serde(skip_serializing_if = "Option::is_none")]
467 pub height: Option<u32>,
468 #[serde(skip_serializing_if = "Option::is_none")]
470 pub duration: Option<u32>,
471 #[serde(skip_serializing_if = "Option::is_none")]
473 pub supports_streaming: Option<bool>,
474}
475
476#[derive(Debug, Clone, Serialize, Deserialize)]
481#[serde(tag = "type", rename_all = "snake_case")]
482pub enum InputPaidMedia {
483 Photo(InputPaidMediaPhoto),
485 Video(InputPaidMediaVideo),
487}
488
489#[derive(Debug, Clone, Serialize, Deserialize)]
493pub struct InputProfilePhotoStatic {
494 pub photo: String,
499}
500
501#[derive(Debug, Clone, Serialize, Deserialize)]
503pub struct InputProfilePhotoAnimated {
504 pub animation: String,
509 #[serde(skip_serializing_if = "Option::is_none")]
512 pub main_frame_timestamp: Option<f64>,
513}
514
515#[derive(Debug, Clone, Serialize, Deserialize)]
519#[serde(tag = "type", rename_all = "snake_case")]
520pub enum InputProfilePhoto {
521 Static(InputProfilePhotoStatic),
523 Animated(InputProfilePhotoAnimated),
525}