use chrono::Utc;
use mobot_derive::BotRequest;
use serde::{Deserialize, Serialize};
use super::{chat::Chat, sticker::Sticker, user::User, Document, PhotoSize, ReplyMarkup, API};
#[derive(Default, Debug, Clone, Deserialize, Serialize)]
pub struct Message {
pub message_id: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub from: Option<User>,
pub date: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub photo: Option<Vec<PhotoSize>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub document: Option<Document>,
pub chat: Chat,
#[serde(skip_serializing_if = "Option::is_none")]
pub forward_from: Option<User>,
#[serde(skip_serializing_if = "Option::is_none")]
pub forward_from_chat: Option<Chat>,
#[serde(skip_serializing_if = "Option::is_none")]
pub forward_from_message_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub forward_signature: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub forward_sender_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub forward_date: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_to_message: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sticker: Option<Sticker>,
#[serde(flatten, skip_serializing_if = "Option::is_none")]
pub reply_markup: Option<ReplyMarkup>,
}
impl Message {
pub fn new(from: impl Into<String>, text: impl Into<String>) -> Self {
let mut message = Message::fake(from.into());
message.text = Some(text.into());
message
}
pub fn fake(from: impl AsRef<str>) -> Self {
Message {
message_id: rand::random(),
from: Some(from.as_ref().into()),
date: Utc::now().timestamp(),
chat: from.as_ref().into(),
..Default::default()
}
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
pub enum ParseMode {
#[serde(rename = "MarkdownV2")]
MarkdownV2,
#[serde(rename = "Markdown")]
Markdown,
#[serde(rename = "HTML")]
HTML,
#[serde(rename = "")]
Text,
}
#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
pub struct SendMessageRequest {
pub chat_id: i64,
pub text: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_to_message_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parse_mode: Option<ParseMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_markup: Option<ReplyMarkup>,
}
impl SendMessageRequest {
pub fn new(chat_id: i64, text: impl Into<String>) -> Self {
Self {
chat_id,
text: text.into(),
..Default::default()
}
}
pub fn with_reply_markup(mut self, reply_markup: ReplyMarkup) -> Self {
self.reply_markup = Some(reply_markup);
self
}
pub fn with_parse_mode(mut self, parse_mode: ParseMode) -> Self {
self.parse_mode = Some(parse_mode);
self
}
}
#[derive(Default, Debug, Serialize, Deserialize, Clone)]
pub struct EditMessageBase {
#[serde(skip_serializing_if = "Option::is_none")]
pub chat_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub message_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub inline_message_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parse_mode: Option<ParseMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_markup: Option<String>,
}
impl EditMessageBase {
pub fn new() -> Self {
Self::default()
}
pub fn with_chat_id(mut self, chat_id: i64) -> Self {
self.chat_id = Some(chat_id);
self
}
pub fn with_message_id(mut self, message_id: i64) -> Self {
self.message_id = Some(message_id);
self
}
pub fn with_parse_mode(mut self, parse_mode: ParseMode) -> Self {
self.parse_mode = Some(parse_mode);
self
}
pub fn with_reply_markup(mut self, reply_markup: ReplyMarkup) -> Self {
self.reply_markup = Some(serde_json::to_string(&reply_markup).unwrap());
self
}
}
#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
pub struct EditMessageTextRequest {
#[serde(flatten)]
pub base: EditMessageBase,
pub text: String,
}
impl EditMessageTextRequest {
pub fn new(text: String) -> Self {
Self {
base: EditMessageBase::new(),
text,
}
}
pub fn with_chat_id(mut self, chat_id: i64) -> Self {
self.base.chat_id = Some(chat_id);
self
}
pub fn with_message_id(mut self, message_id: i64) -> Self {
self.base.message_id = Some(message_id);
self
}
}
#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
pub struct EditMessageCaptionRequest {
#[serde(flatten)]
pub base: EditMessageBase,
pub caption: String,
}
impl EditMessageCaptionRequest {
pub fn new(caption: String) -> Self {
Self {
base: EditMessageBase::new(),
caption,
}
}
pub fn with_chat_id(mut self, chat_id: i64) -> Self {
self.base.chat_id = Some(chat_id);
self
}
}
#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
pub struct EditMessageReplyMarkupRequest {
#[serde(flatten)]
pub base: EditMessageBase,
}
impl EditMessageReplyMarkupRequest {
pub fn new(reply_markup: ReplyMarkup) -> Self {
Self {
base: EditMessageBase::new().with_reply_markup(reply_markup),
}
}
pub fn with_chat_id(mut self, chat_id: i64) -> Self {
self.base.chat_id = Some(chat_id);
self
}
pub fn with_message_id(mut self, message_id: i64) -> Self {
self.base.message_id = Some(message_id);
self
}
}
#[derive(Default, Debug, Serialize, Deserialize, Clone, BotRequest)]
pub struct DeleteMessageRequest {
pub chat_id: i64,
pub message_id: i64,
}
impl DeleteMessageRequest {
pub fn new(chat_id: i64, message_id: i64) -> Self {
Self {
chat_id,
message_id,
}
}
}
impl API {
pub async fn send_message(&self, req: &SendMessageRequest) -> anyhow::Result<Message> {
self.client.post("sendMessage", req).await
}
pub async fn edit_message_text(&self, req: &EditMessageTextRequest) -> anyhow::Result<Message> {
self.client.post("editMessageText", req).await
}
pub async fn edit_message_caption(
&self,
req: &EditMessageCaptionRequest,
) -> anyhow::Result<Message> {
self.client.post("editMessageCaption", req).await
}
pub async fn edit_message_reply_markup(
&self,
req: &EditMessageReplyMarkupRequest,
) -> anyhow::Result<Message> {
self.client.post("editMessageReplyMarkup", req).await
}
pub async fn delete_message(&self, req: &DeleteMessageRequest) -> anyhow::Result<bool> {
self.client.post("deleteMessage", req).await
}
pub async fn remove_reply_keyboard(
&self,
chat_id: i64,
text: String,
) -> anyhow::Result<Message> {
self.send_message(
&SendMessageRequest::new(chat_id, text)
.with_reply_markup(ReplyMarkup::reply_keyboard_remove()),
)
.await
}
}