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