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}