1use chrono::Utc;
2use mobot_derive::BotRequest;
3use serde::{Deserialize, Serialize};
4
5use super::{chat::Chat, sticker::Sticker, user::User, Document, PhotoSize, ReplyMarkup, API};
6
7#[derive(Default, Debug, Clone, Deserialize, Serialize)]
10pub struct Message {
11 pub message_id: i64,
13
14 #[serde(skip_serializing_if = "Option::is_none")]
16 pub from: Option<User>,
17
18 pub date: i64,
20
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub text: Option<String>,
24
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub photo: Option<Vec<PhotoSize>>,
28
29 #[serde(skip_serializing_if = "Option::is_none")]
31 pub document: Option<Document>,
32
33 pub chat: Chat,
38
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub forward_from: Option<User>,
42
43 #[serde(skip_serializing_if = "Option::is_none")]
45 pub forward_from_chat: Option<Chat>,
46
47 #[serde(skip_serializing_if = "Option::is_none")]
49 pub forward_from_message_id: Option<i64>,
50
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub forward_signature: Option<String>,
54
55 #[serde(skip_serializing_if = "Option::is_none")]
57 pub forward_sender_name: Option<String>,
58
59 #[serde(skip_serializing_if = "Option::is_none")]
61 pub forward_date: Option<i64>,
62
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub reply_to_message: Option<i64>,
66
67 #[serde(skip_serializing_if = "Option::is_none")]
69 pub sticker: Option<Sticker>,
70
71 #[serde(flatten, skip_serializing_if = "Option::is_none")]
73 pub reply_markup: Option<ReplyMarkup>,
74}
75
76impl Message {
77 pub fn new(from: impl Into<String>, text: impl Into<String>) -> Self {
79 let mut message = Message::fake(from.into());
80 message.text = Some(text.into());
81 message
82 }
83
84 pub fn fake(from: impl AsRef<str>) -> Self {
85 Message {
86 message_id: rand::random(),
87 from: Some(from.as_ref().into()),
88 date: Utc::now().timestamp(),
89 chat: from.as_ref().into(),
90 ..Default::default()
91 }
92 }
93}
94
95#[derive(Debug, Deserialize, Serialize, Clone)]
96pub enum ParseMode {
97 #[serde(rename = "MarkdownV2")]
98 MarkdownV2,
99 #[serde(rename = "Markdown")]
100 Markdown,
101 #[serde(rename = "HTML")]
102 HTML,
103 #[serde(rename = "")]
104 Text,
105}
106
107#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
108pub struct SendMessageRequest {
109 pub chat_id: i64,
111
112 pub text: String,
114
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub reply_to_message_id: Option<i64>,
118
119 #[serde(skip_serializing_if = "Option::is_none")]
121 pub parse_mode: Option<ParseMode>,
122
123 #[serde(skip_serializing_if = "Option::is_none")]
125 pub reply_markup: Option<ReplyMarkup>,
126}
127
128impl SendMessageRequest {
129 pub fn new(chat_id: i64, text: impl Into<String>) -> Self {
130 Self {
131 chat_id,
132 text: text.into(),
133 ..Default::default()
134 }
135 }
136
137 pub fn with_reply_markup(mut self, reply_markup: ReplyMarkup) -> Self {
138 self.reply_markup = Some(reply_markup);
139 self
140 }
141
142 pub fn with_parse_mode(mut self, parse_mode: ParseMode) -> Self {
143 self.parse_mode = Some(parse_mode);
144 self
145 }
146}
147
148#[derive(Default, Debug, Serialize, Deserialize, Clone)]
149pub struct EditMessageBase {
150 #[serde(skip_serializing_if = "Option::is_none")]
153 pub chat_id: Option<i64>,
154
155 #[serde(skip_serializing_if = "Option::is_none")]
158 pub message_id: Option<i64>,
159
160 #[serde(skip_serializing_if = "Option::is_none")]
162 pub inline_message_id: Option<String>,
163
164 #[serde(skip_serializing_if = "Option::is_none")]
167 pub parse_mode: Option<ParseMode>,
168
169 #[serde(skip_serializing_if = "Option::is_none")]
171 pub reply_markup: Option<String>,
172}
173
174impl EditMessageBase {
175 pub fn new() -> Self {
176 Self::default()
177 }
178
179 pub fn with_chat_id(mut self, chat_id: i64) -> Self {
180 self.chat_id = Some(chat_id);
181 self
182 }
183
184 pub fn with_message_id(mut self, message_id: i64) -> Self {
185 self.message_id = Some(message_id);
186 self
187 }
188
189 pub fn with_parse_mode(mut self, parse_mode: ParseMode) -> Self {
190 self.parse_mode = Some(parse_mode);
191 self
192 }
193
194 pub fn with_reply_markup(mut self, reply_markup: ReplyMarkup) -> Self {
195 self.reply_markup = Some(serde_json::to_string(&reply_markup).unwrap());
196 self
197 }
198}
199
200#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
201pub struct EditMessageTextRequest {
202 #[serde(flatten)]
204 pub base: EditMessageBase,
205
206 pub text: String,
209}
210
211impl EditMessageTextRequest {
212 pub fn new(text: String) -> Self {
213 Self {
214 base: EditMessageBase::new(),
215 text,
216 }
217 }
218
219 pub fn with_chat_id(mut self, chat_id: i64) -> Self {
220 self.base.chat_id = Some(chat_id);
221 self
222 }
223
224 pub fn with_message_id(mut self, message_id: i64) -> Self {
225 self.base.message_id = Some(message_id);
226 self
227 }
228}
229
230#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
231pub struct EditMessageCaptionRequest {
232 #[serde(flatten)]
234 pub base: EditMessageBase,
235
236 pub caption: String,
239}
240
241impl EditMessageCaptionRequest {
242 pub fn new(caption: String) -> Self {
243 Self {
244 base: EditMessageBase::new(),
245 caption,
246 }
247 }
248
249 pub fn with_chat_id(mut self, chat_id: i64) -> Self {
250 self.base.chat_id = Some(chat_id);
251 self
252 }
253}
254
255#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
256pub struct EditMessageReplyMarkupRequest {
257 #[serde(flatten)]
259 pub base: EditMessageBase,
260}
261
262impl EditMessageReplyMarkupRequest {
263 pub fn new(reply_markup: ReplyMarkup) -> Self {
264 Self {
265 base: EditMessageBase::new().with_reply_markup(reply_markup),
266 }
267 }
268
269 pub fn with_chat_id(mut self, chat_id: i64) -> Self {
270 self.base.chat_id = Some(chat_id);
271 self
272 }
273
274 pub fn with_message_id(mut self, message_id: i64) -> Self {
275 self.base.message_id = Some(message_id);
276 self
277 }
278}
279
280#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
281pub struct DeleteMessageRequest {
282 pub chat_id: i64,
285
286 pub message_id: i64,
288}
289
290impl DeleteMessageRequest {
291 pub fn new(chat_id: i64, message_id: i64) -> Self {
292 Self {
293 chat_id,
294 message_id,
295 }
296 }
297}
298
299impl API {
301 pub async fn send_message(&self, req: &SendMessageRequest) -> anyhow::Result<Message> {
315 self.client.post("sendMessage", req).await
316 }
317
318 pub async fn edit_message_text(&self, req: &EditMessageTextRequest) -> anyhow::Result<Message> {
337 self.client.post("editMessageText", req).await
338 }
339
340 pub async fn edit_message_caption(
342 &self,
343 req: &EditMessageCaptionRequest,
344 ) -> anyhow::Result<Message> {
345 self.client.post("editMessageCaption", req).await
346 }
347
348 pub async fn edit_message_reply_markup(
350 &self,
351 req: &EditMessageReplyMarkupRequest,
352 ) -> anyhow::Result<Message> {
353 self.client.post("editMessageReplyMarkup", req).await
354 }
355
356 pub async fn delete_message(&self, req: &DeleteMessageRequest) -> anyhow::Result<bool> {
358 self.client.post("deleteMessage", req).await
359 }
360
361 pub async fn remove_reply_keyboard(
362 &self,
363 chat_id: i64,
364 text: String,
365 ) -> anyhow::Result<Message> {
366 self.send_message(
367 &SendMessageRequest::new(chat_id, text)
368 .with_reply_markup(ReplyMarkup::reply_keyboard_remove()),
369 )
370 .await
371 }
372}