tgbot/types/definitions/file/photo.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 SuggestedPostParameters,
16 SuggestedPostParametersError,
17 TextEntities,
18 TextEntity,
19 TextEntityError,
20 },
21};
22
23/// Represents a size of a photo or a file / sticker thumbnail.
24#[serde_with::skip_serializing_none]
25#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
26pub struct PhotoSize {
27 /// Identifier of the file.
28 ///
29 /// Can be used to download or reuse the file.
30 pub file_id: String,
31 /// Unique identifier of the file.
32 ///
33 /// It is supposed to be the same over time and for different bots.
34 /// Can't be used to download or reuse the file.
35 pub file_unique_id: String,
36 /// Height of the photo.
37 pub height: Integer,
38 /// Width of the photo.
39 pub width: Integer,
40 /// File size in bytes.
41 pub file_size: Option<Integer>,
42}
43
44impl PhotoSize {
45 /// Creates a new `PhotoSize`.
46 ///
47 /// # Arguments
48 ///
49 /// * `file_id` - Identifier of the file.
50 /// * `file_unique_id` - Unique identifier of the file.
51 /// * `height` - Height of the photo.
52 /// * `width` - Width of the photo.
53 pub fn new<A, B>(file_id: A, file_unique_id: B, height: Integer, width: Integer) -> Self
54 where
55 A: Into<String>,
56 B: Into<String>,
57 {
58 Self {
59 file_id: file_id.into(),
60 file_unique_id: file_unique_id.into(),
61 height,
62 width,
63 file_size: 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
78/// Sends a photo.
79#[derive(Debug)]
80pub struct SendPhoto {
81 form: Form,
82}
83
84impl SendPhoto {
85 /// Creates a new `SendPhoto`.
86 ///
87 /// # Arguments
88 ///
89 /// * `chat_id` - Unique identifier of the target chat.
90 /// * `photo` - Photo to send.
91 pub fn new<A, B>(chat_id: A, photo: B) -> Self
92 where
93 A: Into<ChatId>,
94 B: Into<InputFile>,
95 {
96 Self {
97 form: Form::from([("chat_id", chat_id.into().into()), ("photo", photo.into().into())]),
98 }
99 }
100
101 /// Sets a new value for the `allow_paid_broadcast` flag.
102 ///
103 /// # Arguments
104 ///
105 /// * `value` - Whether to allow up to 1000 messages per second, ignoring broadcasting limits
106 /// for a fee of 0.1 Telegram Stars per message.
107 /// The relevant Stars will be withdrawn from the bot's balance.
108 pub fn with_allow_paid_broadcast(mut self, value: bool) -> Self {
109 self.form.insert_field("allow_paid_broadcast", value);
110 self
111 }
112
113 /// Sets a new business connection ID.
114 ///
115 /// # Arguments
116 ///
117 /// * `value` - Unique identifier of the business connection.
118 pub fn with_business_connection_id<T>(mut self, value: T) -> Self
119 where
120 T: Into<String>,
121 {
122 self.form.insert_field("business_connection_id", value.into());
123 self
124 }
125
126 /// Sets a new caption.
127 ///
128 /// # Arguments
129 ///
130 /// * `value` - Caption; 0-1024 characters.
131 ///
132 /// May also be used when resending documents by `file_id`.
133 pub fn with_caption<T>(mut self, value: T) -> Self
134 where
135 T: Into<String>,
136 {
137 self.form.insert_field("caption", value.into());
138 self
139 }
140
141 /// Sets a new list of caption entities.
142 ///
143 /// # Arguments
144 ///
145 /// * `value` - The list of special entities that appear in the caption.
146 ///
147 /// Caption parse mode will be set to [`None`] when this method is called.
148 pub fn with_caption_entities<T>(mut self, value: T) -> Result<Self, TextEntityError>
149 where
150 T: IntoIterator<Item = TextEntity>,
151 {
152 let value: TextEntities = value.into_iter().collect();
153 self.form.insert_field("caption_entities", value.serialize()?);
154 self.form.remove_field("parse_mode");
155 Ok(self)
156 }
157
158 /// Sets a new caption parse mode.
159 ///
160 /// # Arguments
161 ///
162 /// * `value` - Parse mode.
163 ///
164 /// Caption entities will be set to [`None`] when this method is called.
165 pub fn with_caption_parse_mode(mut self, value: ParseMode) -> Self {
166 self.form.insert_field("parse_mode", value);
167 self.form.remove_field("caption_entities");
168 self
169 }
170
171 /// Sets a new direct messages topic ID
172 ///
173 /// * `value` - Identifier of the direct messages topic to which the message will be sent.
174 ///
175 /// Required if the message is sent to a direct messages chat.
176 pub fn with_direct_messages_topic_id(mut self, value: Integer) -> Self {
177 self.form.insert_field("direct_messages_topic_id", value);
178 self
179 }
180
181 /// Sets a new value for the `disable_notification` flag.
182 ///
183 /// # Arguments
184 ///
185 /// * `value` - Indicates whether to send the message silently or not;
186 /// a user will receive a notification without sound.
187 pub fn with_disable_notification(mut self, value: bool) -> Self {
188 self.form.insert_field("disable_notification", value.to_string());
189 self
190 }
191
192 /// Sets a new value for the `has_spoiler` flag.
193 ///
194 /// # Arguments
195 ///
196 /// * `value` - Indicates whether to cover with a spoiler animation.
197 pub fn with_has_spoiler(mut self, value: bool) -> Self {
198 self.form.insert_field("has_spoiler", value);
199 self
200 }
201
202 /// Sets a new message effect ID.
203 ///
204 /// # Arguments
205 ///
206 /// * `value` - Unique identifier of the message effect to be added to the message; for private chats only.
207 pub fn with_message_effect_id<T>(mut self, value: T) -> Self
208 where
209 T: Into<String>,
210 {
211 self.form.insert_field("message_effect_id", value.into());
212 self
213 }
214
215 /// Sets a new message thread ID.
216 ///
217 /// # Arguments
218 ///
219 /// * `value` - Unique identifier of the target message thread;
220 /// supergroups only.
221 pub fn with_message_thread_id(mut self, value: Integer) -> Self {
222 self.form.insert_field("message_thread_id", value);
223 self
224 }
225
226 /// Sets a new value for the `protect_content` flag.
227 ///
228 /// # Arguments
229 ///
230 /// * `value` - Indicates whether to protect the contents
231 /// of the sent message from forwarding and saving.
232 pub fn with_protect_content(mut self, value: bool) -> Self {
233 self.form.insert_field("protect_content", value.to_string());
234 self
235 }
236
237 /// Sets a new reply markup.
238 ///
239 /// # Arguments
240 ///
241 /// * `value` - Reply markup.
242 pub fn with_reply_markup<T>(mut self, value: T) -> Result<Self, ReplyMarkupError>
243 where
244 T: Into<ReplyMarkup>,
245 {
246 let value = value.into();
247 self.form.insert_field("reply_markup", value.serialize()?);
248 Ok(self)
249 }
250
251 /// Sets new reply parameters.
252 ///
253 /// # Arguments
254 ///
255 /// * `value` - Description of the message to reply to.
256 pub fn with_reply_parameters(mut self, value: ReplyParameters) -> Result<Self, ReplyParametersError> {
257 self.form.insert_field("reply_parameters", value.serialize()?);
258 Ok(self)
259 }
260
261 /// Sets a new value for the `show_caption_above_media` flag.
262 ///
263 /// # Arguments
264 ///
265 /// `value` - Whether the caption must be shown above the message media.
266 pub fn with_show_caption_above_media(mut self, value: bool) -> Self {
267 self.form.insert_field("show_caption_above_media", value);
268 self
269 }
270
271 /// Sets a new suggested post parameters.
272 ///
273 /// # Arguments
274 ///
275 /// * `value` - An object containing the parameters of the suggested post to send.
276 ///
277 /// For direct messages chats only.
278 ///
279 /// If the message is sent as a reply to another suggested post, then that suggested post is automatically declined.
280 pub fn with_suggested_post_parameters(
281 mut self,
282 value: &SuggestedPostParameters,
283 ) -> Result<Self, SuggestedPostParametersError> {
284 let value = serde_json::to_string(value).map_err(SuggestedPostParametersError::Serialize)?;
285 self.form.insert_field("suggested_post_parameters", value);
286 Ok(self)
287 }
288}
289
290impl Method for SendPhoto {
291 type Response = Message;
292
293 fn into_payload(self) -> Payload {
294 Payload::form("sendPhoto", self.form)
295 }
296}