tgbot/types/file/voice/mod.rs
1use serde::{Deserialize, Serialize};
2
3use crate::{
4 api::{Form, Method, Payload},
5 types::{
6 ChatId,
7 InputFile,
8 Integer,
9 Message,
10 ParseMode,
11 ReplyMarkup,
12 ReplyMarkupError,
13 ReplyParameters,
14 ReplyParametersError,
15 TextEntities,
16 TextEntity,
17 TextEntityError,
18 },
19};
20
21#[cfg(test)]
22mod tests;
23
24/// Represents a voice file.
25#[serde_with::skip_serializing_none]
26#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
27pub struct Voice {
28 /// Duration in seconds as defined by sender.
29 pub duration: Integer,
30 /// Identifier of the file.
31 ///
32 /// Can be used to download or reuse the file.
33 pub file_id: String,
34 /// Unique identifier of the file.
35 ///
36 /// It is supposed to be the same over time and for different bots.
37 /// Can't be used to download or reuse the file.
38 pub file_unique_id: String,
39 /// File size in bytes.
40 pub file_size: Option<Integer>,
41 /// MIME type as defined by sender.
42 pub mime_type: Option<String>,
43}
44
45impl Voice {
46 /// Creates a new `Voice`.
47 ///
48 /// # Arguments
49 ///
50 /// * `duration` - Duration in seconds.
51 /// * `file_id` - Identifier of the file.
52 /// * `file_unique_id` - Unique identifier of the file.
53 pub fn new<A, B>(duration: Integer, file_id: A, file_unique_id: B) -> Self
54 where
55 A: Into<String>,
56 B: Into<String>,
57 {
58 Self {
59 duration,
60 file_id: file_id.into(),
61 file_unique_id: file_unique_id.into(),
62 file_size: None,
63 mime_type: None,
64 }
65 }
66
67 /// Sets a new size of the file.
68 ///
69 /// # Arguments
70 ///
71 /// * `value` - The size of the file in bytes.
72 pub fn with_file_size(mut self, value: Integer) -> Self {
73 self.file_size = Some(value);
74 self
75 }
76
77 /// Sets a new MIME type.
78 ///
79 /// # Arguments
80 ///
81 /// * `value` - MIME type.
82 pub fn with_mime_type<T>(mut self, value: T) -> Self
83 where
84 T: Into<String>,
85 {
86 self.mime_type = Some(value.into());
87 self
88 }
89}
90
91/// Sends a voice message.
92///
93/// Audio must be in an .ogg file encoded with OPUS, or in .MP3 format, or in .M4A format.
94/// Other formats may be sent as Audio or Document.
95/// Bots can currently send voice messages of up to 50 MB in size,
96/// this limit may be changed in the future.
97#[derive(Debug)]
98pub struct SendVoice {
99 form: Form,
100}
101
102impl SendVoice {
103 /// Creates a new `SendVoice`.
104 ///
105 /// # Arguments
106 ///
107 /// * `chat_id` - Unique identifier of the target chat.
108 /// * `voice` - Audio file to send.
109 pub fn new<A, B>(chat_id: A, voice: B) -> Self
110 where
111 A: Into<ChatId>,
112 B: Into<InputFile>,
113 {
114 Self {
115 form: Form::from([("chat_id", chat_id.into().into()), ("voice", voice.into().into())]),
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 caption.
145 ///
146 /// # Arguments
147 ///
148 /// * `value` - Caption; 0-1024 characters.
149 ///
150 /// May also be used when resending documents by `file_id`.
151 pub fn with_caption<T>(mut self, value: T) -> Self
152 where
153 T: Into<String>,
154 {
155 self.form.insert_field("caption", value.into());
156 self
157 }
158
159 /// Sets a new list of caption entities.
160 ///
161 /// # Arguments
162 ///
163 /// * `value` - The list of special entities that appear in the caption.
164 ///
165 /// Caption parse mode will be set to [`None`] when this method is called.
166 pub fn with_caption_entities<T>(mut self, value: T) -> Result<Self, TextEntityError>
167 where
168 T: IntoIterator<Item = TextEntity>,
169 {
170 let value: TextEntities = value.into_iter().collect();
171 self.form.insert_field("caption_entities", value.serialize()?);
172 self.form.remove_field("parse_mode");
173 Ok(self)
174 }
175
176 /// Sets a new caption parse mode.
177 ///
178 /// # Arguments
179 ///
180 /// * `value` - Parse mode.
181 ///
182 /// Caption entities will be set to [`None`] when this method is called.
183 pub fn with_caption_parse_mode(mut self, value: ParseMode) -> Self {
184 self.form.insert_field("parse_mode", value);
185 self.form.remove_field("caption_entities");
186 self
187 }
188
189 /// Sets a new value for the `disable_notification` flag.
190 ///
191 /// # Arguments
192 ///
193 /// * `value` - Indicates whether to send the message silently or not;
194 /// a user will receive a notification without sound.
195 pub fn with_disable_notification(mut self, value: bool) -> Self {
196 self.form.insert_field("disable_notification", value);
197 self
198 }
199
200 /// Sets a new duration.
201 ///
202 /// # Arguments
203 ///
204 /// * `value` - Duration in seconds.
205 pub fn with_duration(mut self, value: Integer) -> Self {
206 self.form.insert_field("duration", value);
207 self
208 }
209
210 /// Sets a new message effect ID.
211 ///
212 /// # Arguments
213 ///
214 /// * `value` - Unique identifier of the message effect to be added to the message; for private chats only.
215 pub fn with_message_effect_id<T>(mut self, value: T) -> Self
216 where
217 T: Into<String>,
218 {
219 self.form.insert_field("message_effect_id", value.into());
220 self
221 }
222
223 /// Sets a new message thread ID.
224 ///
225 /// # Arguments
226 ///
227 /// * `value` - Unique identifier of the target message thread;
228 /// supergroups only.
229 pub fn with_message_thread_id(mut self, value: Integer) -> Self {
230 self.form.insert_field("message_thread_id", value);
231 self
232 }
233
234 /// Sets a new value for the `protect_content` flag.
235 ///
236 /// # Arguments
237 ///
238 /// * `value` - Indicates whether to protect the contents
239 /// of the sent message from forwarding and saving.
240 pub fn with_protect_content(mut self, value: bool) -> Self {
241 self.form.insert_field("protect_content", value.to_string());
242 self
243 }
244
245 /// Sets a new reply markup.
246 ///
247 /// # Arguments
248 ///
249 /// * `value` - Reply markup.
250 pub fn with_reply_markup<T>(mut self, value: T) -> Result<Self, ReplyMarkupError>
251 where
252 T: Into<ReplyMarkup>,
253 {
254 let value = value.into();
255 self.form.insert_field("reply_markup", value.serialize()?);
256 Ok(self)
257 }
258
259 /// Sets new reply parameters.
260 ///
261 /// # Arguments
262 ///
263 /// * `value` - Description of the message to reply to.
264 pub fn with_reply_parameters(mut self, value: ReplyParameters) -> Result<Self, ReplyParametersError> {
265 self.form.insert_field("reply_parameters", value.serialize()?);
266 Ok(self)
267 }
268}
269
270impl Method for SendVoice {
271 type Response = Message;
272
273 fn into_payload(self) -> Payload {
274 Payload::form("sendVoice", self.form)
275 }
276}