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 {}