tgbot/types/file/video_note/mod.rs
1use std::{error::Error, fmt};
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6 api::{Form, Method, Payload},
7 types::{
8 ChatId,
9 InputFile,
10 Integer,
11 Message,
12 PhotoSize,
13 ReplyMarkup,
14 ReplyMarkupError,
15 ReplyParameters,
16 ReplyParametersError,
17 },
18};
19
20#[cfg(test)]
21mod tests;
22
23/// Represents a video message.
24#[serde_with::skip_serializing_none]
25#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
26pub struct VideoNote {
27 /// Duration in seconds.
28 pub duration: Integer,
29 /// Identifier of the file.
30 ///
31 /// Can be used to download or reuse the file.
32 pub file_id: String,
33 /// Unique identifier of the file.
34 ///
35 /// It is supposed to be the same over time and for different bots.
36 /// Can't be used to download or reuse the file.
37 pub file_unique_id: String,
38 /// Width and height (diameter).
39 pub length: Integer,
40 /// File size in bytes.
41 pub file_size: Option<Integer>,
42 /// Thumbnail.
43 pub thumbnail: Option<PhotoSize>,
44}
45
46impl VideoNote {
47 /// Creates a new `VideoNote`.
48 ///
49 /// # Arguments
50 ///
51 /// * `duration` - Duration in seconds.
52 /// * `file_id` - Identifier of the file.
53 /// * `file_unique_id` - Unique identifier of the file.
54 /// * `length` - Width and height (diameter).
55 pub fn new<A, B>(duration: Integer, file_id: A, file_unique_id: B, length: Integer) -> Self
56 where
57 A: Into<String>,
58 B: Into<String>,
59 {
60 Self {
61 duration,
62 file_id: file_id.into(),
63 file_unique_id: file_unique_id.into(),
64 length,
65 file_size: None,
66 thumbnail: None,
67 }
68 }
69
70 /// Sets a new size of the file.
71 ///
72 /// # Arguments
73 ///
74 /// * `value` - The size of the file in bytes.
75 pub fn with_file_size(mut self, value: Integer) -> Self {
76 self.file_size = Some(value);
77 self
78 }
79
80 /// Sets a new thumbnail.
81 ///
82 /// # Arguments
83 ///
84 /// * `value` - Thumbnail.
85 pub fn with_thumbnail(mut self, value: PhotoSize) -> Self {
86 self.thumbnail = Some(value);
87 self
88 }
89}
90
91/// Sends a video message.
92///
93/// As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1 minute long.
94#[derive(Debug)]
95pub struct SendVideoNote {
96 form: Form,
97}
98
99impl SendVideoNote {
100 /// Creates a new `SendVideoNote`.
101 ///
102 /// # Arguments
103 ///
104 /// * `chat_id` - Unique identifier of the target chat.
105 /// * `video_note` - Video note to send.
106 pub fn new<A, B>(chat_id: A, video_note: B) -> Self
107 where
108 A: Into<ChatId>,
109 B: Into<InputFile>,
110 {
111 Self {
112 form: Form::from([
113 ("chat_id", chat_id.into().into()),
114 ("video_note", video_note.into().into()),
115 ]),
116 }
117 }
118
119 /// Sets a new value for the `allow_paid_broadcast` flag.
120 ///
121 /// # Arguments
122 ///
123 /// * `value` - Whether to allow up to 1000 messages per second, ignoring broadcasting limits
124 /// for a fee of 0.1 Telegram Stars per message.
125 /// The relevant Stars will be withdrawn from the bot's balance.
126 pub fn with_allow_paid_broadcast(mut self, value: bool) -> Self {
127 self.form.insert_field("allow_paid_broadcast", value);
128 self
129 }
130
131 /// Sets a new business connection ID.
132 ///
133 /// # Arguments
134 ///
135 /// * `value` - Unique identifier of the business connection.
136 pub fn with_business_connection_id<T>(mut self, value: T) -> Self
137 where
138 T: Into<String>,
139 {
140 self.form.insert_field("business_connection_id", value.into());
141 self
142 }
143
144 /// Sets a new value for the `disable_notification` flag.
145 ///
146 /// # Arguments
147 ///
148 /// * `value` - Indicates whether to send the message silently or not;
149 /// a user will receive a notification without sound.
150 pub fn with_disable_notification(mut self, value: bool) -> Self {
151 self.form.insert_field("disable_notification", value);
152 self
153 }
154
155 /// Sets a new duration.
156 ///
157 /// # Arguments
158 ///
159 /// * `value` - Duration in seconds.
160 pub fn with_duration(mut self, value: Integer) -> Self {
161 self.form.insert_field("duration", value);
162 self
163 }
164
165 /// Sets a new length.
166 ///
167 /// # Arguments
168 ///
169 /// * `value` - Video width and height, i.e. diameter of the video message.
170 pub fn with_length(mut self, value: Integer) -> Self {
171 self.form.insert_field("length", value);
172 self
173 }
174
175 /// Sets a new message effect ID.
176 ///
177 /// # Arguments
178 ///
179 /// * `value` - Unique identifier of the message effect to be added to the message; for private chats only.
180 pub fn with_message_effect_id<T>(mut self, value: T) -> Self
181 where
182 T: Into<String>,
183 {
184 self.form.insert_field("message_effect_id", value.into());
185 self
186 }
187
188 /// Sets a new message thread ID.
189 ///
190 /// # Arguments
191 ///
192 /// * `value` - Unique identifier of the target message thread;
193 /// supergroups only.
194 pub fn with_message_thread_id(mut self, value: Integer) -> Self {
195 self.form.insert_field("message_thread_id", value);
196 self
197 }
198
199 /// Sets a new value for the `protect_content` flag.
200 ///
201 /// # Arguments
202 ///
203 /// * `value` - Indicates whether to protect the contents
204 /// of the sent message from forwarding and saving.
205 pub fn with_protect_content(mut self, value: bool) -> Self {
206 self.form.insert_field("protect_content", value.to_string());
207 self
208 }
209
210 /// Sets a new reply markup.
211 ///
212 /// # Arguments
213 ///
214 /// * `value` - Reply markup.
215 pub fn with_reply_markup<T>(mut self, value: T) -> Result<Self, ReplyMarkupError>
216 where
217 T: Into<ReplyMarkup>,
218 {
219 let value = value.into();
220 self.form.insert_field("reply_markup", value.serialize()?);
221 Ok(self)
222 }
223
224 /// Sets new reply parameters.
225 ///
226 /// # Arguments
227 ///
228 /// * `value` - Description of the message to reply to.
229 pub fn with_reply_parameters(mut self, value: ReplyParameters) -> Result<Self, ReplyParametersError> {
230 self.form.insert_field("reply_parameters", value.serialize()?);
231 Ok(self)
232 }
233
234 /// Sets a new thumbnail.
235 ///
236 /// # Arguments
237 ///
238 /// * `value` - Thumbnail.
239 ///
240 /// The thumbnail should be in JPEG format and less than 200 kB in size.
241 /// A thumbnail‘s width and height should not exceed 320.
242 /// Ignored if the file is not uploaded using `multipart/form-data`.
243 /// Thumbnails can’t be reused and can be only uploaded as a new file.
244 pub fn with_thumbnail<T>(mut self, value: T) -> Result<Self, SendVideoNoteError>
245 where
246 T: Into<InputFile>,
247 {
248 let value = value.into();
249 if matches!(value, InputFile::Id(_)) {
250 return Err(SendVideoNoteError::InvalidThumbnail);
251 }
252 self.form.insert_field("thumbnail", value);
253 Ok(self)
254 }
255}
256
257impl Method for SendVideoNote {
258 type Response = Message;
259
260 fn into_payload(self) -> Payload {
261 Payload::form("sendVideoNote", self.form)
262 }
263}
264
265/// Represents an error when sending a video note.
266#[derive(Debug)]
267pub enum SendVideoNoteError {
268 /// Thumbnails can not be reused.
269 InvalidThumbnail,
270}
271
272impl fmt::Display for SendVideoNoteError {
273 fn fmt(&self, out: &mut fmt::Formatter<'_>) -> fmt::Result {
274 match self {
275 Self::InvalidThumbnail => write!(out, "thumbnails can’t be reused and can be only uploaded as a new file"),
276 }
277 }
278}
279
280impl Error for SendVideoNoteError {}