use std::future::{Future, IntoFuture};
use std::pin::Pin;
use serde::Serialize;
use rustigram_types::checklist::InputChecklist;
use rustigram_types::keyboard::InlineKeyboardMarkup;
use rustigram_types::message::{LinkPreviewOptions, Message, MessageEntity, ParseMode};
use rustigram_types::rich_message::InputRichMessage;
use rustigram_types::user::ChatId;
use crate::client::BotClient;
use crate::error::Result;
macro_rules! impl_into_future {
($builder:ident, $return_ty:ty, $method:literal) => {
impl IntoFuture for $builder {
type Output = Result<$return_ty>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
fn into_future(self) -> Self::IntoFuture {
Box::pin(async move { self.client.post_json($method, &self.params).await })
}
}
};
}
#[derive(Serialize)]
#[serde(untagged)]
pub enum EditTarget {
Chat {
chat_id: ChatId,
message_id: i64,
},
Inline {
inline_message_id: String,
},
}
#[derive(Serialize)]
struct EditMessageTextParams {
#[serde(flatten)]
target: EditTarget,
#[serde(skip_serializing_if = "Option::is_none")]
text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
rich_message: Option<InputRichMessage>,
#[serde(skip_serializing_if = "Option::is_none")]
business_connection_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
parse_mode: Option<ParseMode>,
#[serde(skip_serializing_if = "Option::is_none")]
entities: Option<Vec<MessageEntity>>,
#[serde(skip_serializing_if = "Option::is_none")]
link_preview_options: Option<LinkPreviewOptions>,
#[serde(skip_serializing_if = "Option::is_none")]
reply_markup: Option<InlineKeyboardMarkup>,
}
pub struct EditMessageText {
client: BotClient,
params: EditMessageTextParams,
}
impl EditMessageText {
pub(crate) fn in_chat(
client: BotClient,
chat_id: impl Into<ChatId>,
message_id: i64,
text: impl Into<String>,
) -> Self {
Self {
client,
params: EditMessageTextParams {
target: EditTarget::Chat {
chat_id: chat_id.into(),
message_id,
},
text: Some(text.into()),
rich_message: None,
business_connection_id: None,
parse_mode: None,
entities: None,
link_preview_options: None,
reply_markup: None,
},
}
}
pub(crate) fn inline(
client: BotClient,
inline_message_id: impl Into<String>,
text: impl Into<String>,
) -> Self {
Self {
client,
params: EditMessageTextParams {
target: EditTarget::Inline {
inline_message_id: inline_message_id.into(),
},
text: Some(text.into()),
rich_message: None,
business_connection_id: None,
parse_mode: None,
entities: None,
link_preview_options: None,
reply_markup: None,
},
}
}
pub(crate) fn in_chat_rich(
client: BotClient,
chat_id: impl Into<ChatId>,
message_id: i64,
rich_message: InputRichMessage,
) -> Self {
Self {
client,
params: EditMessageTextParams {
target: EditTarget::Chat {
chat_id: chat_id.into(),
message_id,
},
text: None,
rich_message: Some(rich_message),
business_connection_id: None,
parse_mode: None,
entities: None,
link_preview_options: None,
reply_markup: None,
},
}
}
pub(crate) fn inline_rich(
client: BotClient,
inline_message_id: impl Into<String>,
rich_message: InputRichMessage,
) -> Self {
Self {
client,
params: EditMessageTextParams {
target: EditTarget::Inline {
inline_message_id: inline_message_id.into(),
},
text: None,
rich_message: Some(rich_message),
business_connection_id: None,
parse_mode: None,
entities: None,
link_preview_options: None,
reply_markup: None,
},
}
}
pub fn parse_mode(mut self, m: ParseMode) -> Self {
self.params.parse_mode = Some(m);
self
}
pub fn entities(mut self, e: Vec<MessageEntity>) -> Self {
self.params.entities = Some(e);
self
}
pub fn link_preview_options(mut self, o: LinkPreviewOptions) -> Self {
self.params.link_preview_options = Some(o);
self
}
pub fn reply_markup(mut self, m: InlineKeyboardMarkup) -> Self {
self.params.reply_markup = Some(m);
self
}
}
impl_into_future!(EditMessageText, Message, "editMessageText");
#[derive(Serialize)]
struct EditMessageCaptionParams {
#[serde(flatten)]
target: EditTarget,
#[serde(skip_serializing_if = "Option::is_none")]
business_connection_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
caption: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
parse_mode: Option<ParseMode>,
#[serde(skip_serializing_if = "Option::is_none")]
caption_entities: Option<Vec<MessageEntity>>,
#[serde(skip_serializing_if = "Option::is_none")]
show_caption_above_media: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
reply_markup: Option<InlineKeyboardMarkup>,
}
pub struct EditMessageCaption {
client: BotClient,
params: EditMessageCaptionParams,
}
impl EditMessageCaption {
pub(crate) fn in_chat(client: BotClient, chat_id: impl Into<ChatId>, message_id: i64) -> Self {
Self {
client,
params: EditMessageCaptionParams {
target: EditTarget::Chat {
chat_id: chat_id.into(),
message_id,
},
business_connection_id: None,
caption: None,
parse_mode: None,
caption_entities: None,
show_caption_above_media: None,
reply_markup: None,
},
}
}
pub(crate) fn inline(client: BotClient, inline_message_id: impl Into<String>) -> Self {
Self {
client,
params: EditMessageCaptionParams {
target: EditTarget::Inline {
inline_message_id: inline_message_id.into(),
},
business_connection_id: None,
caption: None,
parse_mode: None,
caption_entities: None,
show_caption_above_media: None,
reply_markup: None,
},
}
}
pub fn caption(mut self, c: impl Into<String>) -> Self {
self.params.caption = Some(c.into());
self
}
pub fn parse_mode(mut self, m: ParseMode) -> Self {
self.params.parse_mode = Some(m);
self
}
pub fn show_caption_above_media(mut self, v: bool) -> Self {
self.params.show_caption_above_media = Some(v);
self
}
pub fn reply_markup(mut self, m: InlineKeyboardMarkup) -> Self {
self.params.reply_markup = Some(m);
self
}
}
impl_into_future!(EditMessageCaption, Message, "editMessageCaption");
#[derive(Serialize)]
struct EditMessageMediaParams {
#[serde(flatten)]
target: EditTarget,
media: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
business_connection_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
reply_markup: Option<InlineKeyboardMarkup>,
}
pub struct EditMessageMedia {
client: BotClient,
params: EditMessageMediaParams,
}
impl EditMessageMedia {
pub(crate) fn in_chat(
client: BotClient,
chat_id: impl Into<ChatId>,
message_id: i64,
media: serde_json::Value,
) -> Self {
Self {
client,
params: EditMessageMediaParams {
target: EditTarget::Chat {
chat_id: chat_id.into(),
message_id,
},
media,
business_connection_id: None,
reply_markup: None,
},
}
}
pub(crate) fn inline(
client: BotClient,
inline_message_id: impl Into<String>,
media: serde_json::Value,
) -> Self {
Self {
client,
params: EditMessageMediaParams {
target: EditTarget::Inline {
inline_message_id: inline_message_id.into(),
},
media,
business_connection_id: None,
reply_markup: None,
},
}
}
pub fn business_connection_id(mut self, id: impl Into<String>) -> Self {
self.params.business_connection_id = Some(id.into());
self
}
pub fn reply_markup(mut self, m: InlineKeyboardMarkup) -> Self {
self.params.reply_markup = Some(m);
self
}
}
impl_into_future!(EditMessageMedia, Message, "editMessageMedia");
#[derive(Serialize)]
struct EditMessageReplyMarkupParams {
#[serde(flatten)]
target: EditTarget,
#[serde(skip_serializing_if = "Option::is_none")]
business_connection_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
reply_markup: Option<InlineKeyboardMarkup>,
}
pub struct EditMessageReplyMarkup {
client: BotClient,
params: EditMessageReplyMarkupParams,
}
impl EditMessageReplyMarkup {
pub(crate) fn in_chat(client: BotClient, chat_id: impl Into<ChatId>, message_id: i64) -> Self {
Self {
client,
params: EditMessageReplyMarkupParams {
target: EditTarget::Chat {
chat_id: chat_id.into(),
message_id,
},
business_connection_id: None,
reply_markup: None,
},
}
}
pub(crate) fn inline(client: BotClient, inline_message_id: impl Into<String>) -> Self {
Self {
client,
params: EditMessageReplyMarkupParams {
target: EditTarget::Inline {
inline_message_id: inline_message_id.into(),
},
business_connection_id: None,
reply_markup: None,
},
}
}
pub fn reply_markup(mut self, m: InlineKeyboardMarkup) -> Self {
self.params.reply_markup = Some(m);
self
}
pub fn remove_markup(mut self) -> Self {
self.params.reply_markup = None;
self
}
}
impl_into_future!(EditMessageReplyMarkup, Message, "editMessageReplyMarkup");
#[derive(Serialize)]
struct EditMessageChecklistParams {
business_connection_id: String,
chat_id: i64,
message_id: i64,
checklist: InputChecklist,
#[serde(skip_serializing_if = "Option::is_none")]
reply_markup: Option<InlineKeyboardMarkup>,
}
pub struct EditMessageChecklist {
client: BotClient,
params: EditMessageChecklistParams,
}
impl EditMessageChecklist {
pub(crate) fn new(
client: BotClient,
business_connection_id: impl Into<String>,
chat_id: i64,
message_id: i64,
checklist: InputChecklist,
) -> Self {
Self {
client,
params: EditMessageChecklistParams {
business_connection_id: business_connection_id.into(),
chat_id,
message_id,
checklist,
reply_markup: None,
},
}
}
pub fn reply_markup(mut self, m: InlineKeyboardMarkup) -> Self {
self.params.reply_markup = Some(m);
self
}
}
impl_into_future!(EditMessageChecklist, Message, "editMessageChecklist");
#[derive(Serialize)]
struct ApproveSuggestedPostParams {
chat_id: i64,
message_id: i64,
#[serde(skip_serializing_if = "Option::is_none")]
send_date: Option<i64>,
}
pub struct ApproveSuggestedPost {
client: BotClient,
params: ApproveSuggestedPostParams,
}
impl ApproveSuggestedPost {
pub(crate) fn new(client: BotClient, chat_id: i64, message_id: i64) -> Self {
Self {
client,
params: ApproveSuggestedPostParams {
chat_id,
message_id,
send_date: None,
},
}
}
pub fn send_date(mut self, ts: i64) -> Self {
self.params.send_date = Some(ts);
self
}
}
impl_into_future!(ApproveSuggestedPost, bool, "approveSuggestedPost");
#[derive(Serialize)]
struct DeclineSuggestedPostParams {
chat_id: i64,
message_id: i64,
#[serde(skip_serializing_if = "Option::is_none")]
comment: Option<String>,
}
pub struct DeclineSuggestedPost {
client: BotClient,
params: DeclineSuggestedPostParams,
}
impl DeclineSuggestedPost {
pub(crate) fn new(client: BotClient, chat_id: i64, message_id: i64) -> Self {
Self {
client,
params: DeclineSuggestedPostParams {
chat_id,
message_id,
comment: None,
},
}
}
pub fn comment(mut self, c: impl Into<String>) -> Self {
self.params.comment = Some(c.into());
self
}
}
impl_into_future!(DeclineSuggestedPost, bool, "declineSuggestedPost");
#[derive(Serialize)]
struct EditMessageLiveLocationParams {
#[serde(flatten)]
target: EditTarget,
latitude: f64,
longitude: f64,
#[serde(skip_serializing_if = "Option::is_none")]
live_period: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
horizontal_accuracy: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
heading: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
proximity_alert_radius: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
reply_markup: Option<InlineKeyboardMarkup>,
}
pub struct EditMessageLiveLocation {
client: BotClient,
params: EditMessageLiveLocationParams,
}
impl EditMessageLiveLocation {
pub(crate) fn in_chat(
client: BotClient,
chat_id: impl Into<ChatId>,
message_id: i64,
latitude: f64,
longitude: f64,
) -> Self {
Self {
client,
params: EditMessageLiveLocationParams {
target: EditTarget::Chat {
chat_id: chat_id.into(),
message_id,
},
latitude,
longitude,
live_period: None,
horizontal_accuracy: None,
heading: None,
proximity_alert_radius: None,
reply_markup: None,
},
}
}
pub(crate) fn inline(
client: BotClient,
inline_message_id: impl Into<String>,
latitude: f64,
longitude: f64,
) -> Self {
Self {
client,
params: EditMessageLiveLocationParams {
target: EditTarget::Inline {
inline_message_id: inline_message_id.into(),
},
latitude,
longitude,
live_period: None,
horizontal_accuracy: None,
heading: None,
proximity_alert_radius: None,
reply_markup: None,
},
}
}
pub fn live_period(mut self, v: u32) -> Self {
self.params.live_period = Some(v);
self
}
pub fn heading(mut self, v: u16) -> Self {
self.params.heading = Some(v);
self
}
pub fn reply_markup(mut self, m: InlineKeyboardMarkup) -> Self {
self.params.reply_markup = Some(m);
self
}
}
impl_into_future!(EditMessageLiveLocation, Message, "editMessageLiveLocation");
#[derive(Serialize)]
struct StopMessageLiveLocationParams {
#[serde(flatten)]
target: EditTarget,
#[serde(skip_serializing_if = "Option::is_none")]
reply_markup: Option<InlineKeyboardMarkup>,
}
pub struct StopMessageLiveLocation {
client: BotClient,
params: StopMessageLiveLocationParams,
}
impl StopMessageLiveLocation {
pub(crate) fn in_chat(client: BotClient, chat_id: impl Into<ChatId>, message_id: i64) -> Self {
Self {
client,
params: StopMessageLiveLocationParams {
target: EditTarget::Chat {
chat_id: chat_id.into(),
message_id,
},
reply_markup: None,
},
}
}
pub(crate) fn inline(client: BotClient, inline_message_id: impl Into<String>) -> Self {
Self {
client,
params: StopMessageLiveLocationParams {
target: EditTarget::Inline {
inline_message_id: inline_message_id.into(),
},
reply_markup: None,
},
}
}
pub fn reply_markup(mut self, m: InlineKeyboardMarkup) -> Self {
self.params.reply_markup = Some(m);
self
}
}
impl_into_future!(StopMessageLiveLocation, Message, "stopMessageLiveLocation");