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")]
32 pub file_path: Option<String>,
33}
34
35impl File {
36 #[must_use]
38 pub fn url(&self, token: &str) -> Option<String> {
39 self.file_path
40 .as_ref()
41 .map(|path| format!("https://api.telegram.org/file/bot{token}/{path}"))
42 }
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct Audio {
48 pub file_id: String,
50 pub file_unique_id: String,
52 pub duration: u32,
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub performer: Option<String>,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub title: Option<String>,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub file_name: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub mime_type: Option<String>,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub file_size: Option<u64>,
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub thumbnail: Option<PhotoSize>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct Document {
77 pub file_id: String,
79 pub file_unique_id: String,
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub thumbnail: Option<PhotoSize>,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub file_name: Option<String>,
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub mime_type: Option<String>,
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub file_size: Option<u64>,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct Video {
98 pub file_id: String,
100 pub file_unique_id: String,
102 pub width: u32,
104 pub height: u32,
106 pub duration: u32,
108 #[serde(skip_serializing_if = "Option::is_none")]
110 pub thumbnail: Option<PhotoSize>,
111 #[serde(skip_serializing_if = "Option::is_none")]
113 pub cover: Option<Vec<PhotoSize>>,
114 #[serde(skip_serializing_if = "Option::is_none")]
116 pub start_timestamp: Option<u32>,
117 #[serde(skip_serializing_if = "Option::is_none")]
119 pub file_name: Option<String>,
120 #[serde(skip_serializing_if = "Option::is_none")]
122 pub mime_type: Option<String>,
123 #[serde(skip_serializing_if = "Option::is_none")]
125 pub file_size: Option<u64>,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
130pub struct Animation {
131 pub file_id: String,
133 pub file_unique_id: String,
135 pub width: u32,
137 pub height: u32,
139 pub duration: u32,
141 #[serde(skip_serializing_if = "Option::is_none")]
143 pub thumbnail: Option<PhotoSize>,
144 #[serde(skip_serializing_if = "Option::is_none")]
146 pub file_name: Option<String>,
147 #[serde(skip_serializing_if = "Option::is_none")]
149 pub mime_type: Option<String>,
150 #[serde(skip_serializing_if = "Option::is_none")]
152 pub file_size: Option<u64>,
153}
154
155#[derive(Debug, Clone, Serialize, Deserialize)]
157pub struct Voice {
158 pub file_id: String,
160 pub file_unique_id: String,
162 pub duration: u32,
164 #[serde(skip_serializing_if = "Option::is_none")]
166 pub mime_type: Option<String>,
167 #[serde(skip_serializing_if = "Option::is_none")]
169 pub file_size: Option<u64>,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct VideoNote {
175 pub file_id: String,
177 pub file_unique_id: String,
179 pub length: u32,
181 pub duration: u32,
183 #[serde(skip_serializing_if = "Option::is_none")]
185 pub thumbnail: Option<PhotoSize>,
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub file_size: Option<u64>,
189}
190
191#[derive(Debug, Clone)]
193pub enum InputFile {
194 FileId(String),
196 Url(String),
198 Bytes {
200 filename: String,
202 data: Vec<u8>,
204 mime_type: String,
206 },
207 Attach(String),
209}
210
211impl InputFile {
212 #[must_use]
214 pub fn as_str(&self) -> &str {
215 match self {
216 Self::FileId(id) => id,
217 Self::Url(url) => url,
218 Self::Attach(name) => name,
219 Self::Bytes { filename, .. } => filename,
220 }
221 }
222
223 #[must_use]
225 pub fn requires_multipart(&self) -> bool {
226 matches!(self, Self::Bytes { .. })
227 }
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct PassportFile {
233 pub file_id: String,
235 pub file_unique_id: String,
237 pub file_size: u64,
239 pub file_date: i64,
241}