use serde::{Deserialize, Serialize};
use crate::markup::{InlineKeyboardMarkup, MessageEntity, ParseMode};
use crate::message::{Location, Message};
use crate::payment::LabeledPrice;
use crate::user::User;
use crate::{JsonMethod, TelegramMethod};
#[derive(Debug, Deserialize)]
pub struct InlineQuery {
pub id: String,
pub from: User,
pub query: String,
pub offset: String,
pub chat_type: Option<String>,
pub location: Option<Location>,
}
#[derive(Debug, Deserialize)]
pub struct ChosenInlineResult {}
#[derive(Debug, Deserialize)]
pub struct CallbackQuery {
pub id: String,
pub from: User,
pub message: Option<Message>,
pub inline_message_id: Option<String>,
pub chat_instance: String,
pub data: Option<String>,
pub game_short_name: Option<String>,
}
#[derive(Clone, Serialize)]
pub struct InlineQueryResult {
pub id: String,
r#type: &'static str,
#[serde(flatten)]
pub kind: InlineQueryResultKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_markup: Option<InlineKeyboardMarkup>,
}
impl InlineQueryResult {
pub fn with_reply_markup(self, markup: impl Into<InlineKeyboardMarkup>) -> Self {
Self {
reply_markup: Some(markup.into()),
..self
}
}
}
#[derive(Clone, Serialize)]
#[serde(untagged)]
pub enum InlineQueryResultKind {
Article {
title: String,
input_message_content: InputMessageContent,
#[serde(skip_serializing_if = "Option::is_none")]
url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
hide_url: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_height: Option<u32>,
},
Photo {
photo_url: String,
thumb_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
photo_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
photo_height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
description: 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")]
input_message_content: Option<InputMessageContent>,
},
Gif {
gif_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
gif_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
gif_height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
gif_duration: Option<u32>,
thumb_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_mime_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
title: 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")]
input_message_content: Option<InputMessageContent>,
},
Mpeg4Gif {
mpeg4_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
mpeg4_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
mpeg4_height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
mpeg4_duration: Option<u32>,
thumb_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_mime_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
title: 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")]
input_message_content: Option<InputMessageContent>,
},
Video {
video_url: String,
mime_type: String,
thumb_url: String,
title: String,
#[serde(skip_serializing_if = "Option::is_none")]
video_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
video_height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
video_duration: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
description: 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")]
input_message_content: Option<InputMessageContent>,
},
Audio {
audio_url: String,
title: String,
performer: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
audio_duration: Option<u32>,
#[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")]
input_message_content: Option<InputMessageContent>,
},
Voice {
voice_url: String,
title: String,
#[serde(skip_serializing_if = "Option::is_none")]
voice_duration: Option<u32>,
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")]
input_message_content: Option<InputMessageContent>,
},
Document {
document_url: String,
mime_type: String,
description: String,
thumb_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_height: Option<u32>,
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")]
input_message_content: Option<InputMessageContent>,
},
Location {
latitude: f32,
longitude: f32,
title: String,
horizontal_accuracy: f32,
#[serde(skip_serializing_if = "Option::is_none")]
live_period: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
heading: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
proximity_alert_radius: Option<u32>,
thumb_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
input_message_content: Option<InputMessageContent>,
},
Venue {
latitude: f32,
longitude: f32,
title: String,
address: String,
#[serde(skip_serializing_if = "Option::is_none")]
foursquare_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
foursquare_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
google_place_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
google_place_type: Option<String>,
thumb_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
input_message_content: Option<InputMessageContent>,
},
Contact {
phone_number: String,
first_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
last_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
vcard: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
thumb_height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
input_message_content: Option<InputMessageContent>,
},
Game {
game_short_name: String,
},
CachedPhoto {
photo_file_id: String,
title: String,
#[serde(skip_serializing_if = "Option::is_none")]
description: 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")]
input_message_content: Option<InputMessageContent>,
},
CachedGif {
gif_file_id: String,
title: 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")]
input_message_content: Option<InputMessageContent>,
},
CachedMpeg4Gif {
mpeg4_file_id: String,
title: 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")]
input_message_content: Option<InputMessageContent>,
},
CachedVideo {
video_file_id: String,
title: String,
#[serde(skip_serializing_if = "Option::is_none")]
description: 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")]
input_message_content: Option<InputMessageContent>,
},
CachedAudio {
audio_file_id: 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")]
input_message_content: Option<InputMessageContent>,
},
CachedVoice {
voice_file_id: String,
title: 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")]
input_message_content: Option<InputMessageContent>,
},
CachedDocument {
document_file_id: String,
title: String,
description: 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")]
input_message_content: Option<InputMessageContent>,
},
}
impl InlineQueryResultKind {
pub fn with_id(self, id: impl Into<String>) -> InlineQueryResult {
use InlineQueryResultKind::*;
let r#type = match self {
Article { .. } => "article",
Photo { .. } | CachedPhoto { .. } => "photo",
Gif { .. } | CachedGif { .. } => "gif",
Mpeg4Gif { .. } | CachedMpeg4Gif { .. } => "mpeg4_gif",
Video { .. } | CachedVideo { .. } => "video",
Audio { .. } | CachedAudio { .. } => "audio",
Voice { .. } | CachedVoice { .. } => "voice",
Document { .. } | CachedDocument { .. } => "document",
Location { .. } => "location",
Venue { .. } => "venue",
Contact { .. } => "contact",
Game { .. } => "game",
};
InlineQueryResult {
id: id.into(),
r#type,
kind: self,
reply_markup: None,
}
}
}
#[derive(Clone, Serialize)]
#[serde(untagged)]
pub enum InputMessageContent {
Text {
message_text: 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")]
disable_web_page_preview: Option<bool>,
},
Location {
latitude: f32,
longitude: f32,
horizontal_accuracy: f32,
#[serde(skip_serializing_if = "Option::is_none")]
live_period: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
heading: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
proximity_alert_radius: Option<u32>,
},
Venue {
latitude: f32,
longitude: f32,
title: String,
address: String,
#[serde(skip_serializing_if = "Option::is_none")]
foursquare_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
foursquare_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
google_place_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
google_place_type: Option<String>,
},
Contact {
phone_number: String,
first_name: String,
#[serde(skip_serializing_if = "Option::is_none")]
last_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
vcard: Option<String>,
},
Invoice {
title: String,
description: String,
payload: String,
provider_token: String,
currency: String,
prices: Vec<LabeledPrice>,
#[serde(skip_serializing_if = "Option::is_none")]
max_tip_amount: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
suggested_tip_amounts: Option<Vec<i32>>,
#[serde(skip_serializing_if = "Option::is_none")]
start_parameter: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
provider_data: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
photo_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
photo_size: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
photo_width: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
photo_height: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
need_name: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
need_phone_number: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
need_email: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
need_shipping_address: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
send_phone_number_to_provider: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
send_email_to_provider: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
is_flexible: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
disable_notification: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
reply_to_message_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
allow_sending_without_reply: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
reply_markup: Option<InlineKeyboardMarkup>,
},
}
#[derive(Clone, Serialize)]
pub struct AnswerCallbackQuery {
pub callback_query_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub show_alert: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cache_time: Option<u32>,
}
impl AnswerCallbackQuery {
pub fn new(query_id: impl Into<String>) -> Self {
Self {
callback_query_id: query_id.into(),
text: None,
show_alert: None,
url: None,
cache_time: None,
}
}
pub fn with_text(self, text: impl Into<String>) -> Self {
Self {
text: Some(text.into()),
..self
}
}
pub fn show_alert(self) -> Self {
Self {
show_alert: Some(true),
..self
}
}
pub fn with_url(self, url: impl Into<String>) -> Self {
Self {
url: Some(url.into()),
..self
}
}
pub fn with_cache_time(self, cache_time: u32) -> Self {
Self {
cache_time: Some(cache_time),
..self
}
}
}
impl TelegramMethod for AnswerCallbackQuery {
type Response = bool;
fn name() -> &'static str {
"answerCallbackQuery"
}
}
impl JsonMethod for AnswerCallbackQuery {}
#[derive(Clone, Serialize)]
pub struct AnswerInlineQuery {
pub inline_query_id: String,
pub results: Vec<InlineQueryResult>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cache_time: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_personal: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub next_offset: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub switch_pm_text: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub switch_pm_parameter: Option<String>,
}
impl AnswerInlineQuery {
pub fn new(query_id: impl Into<String>, results: Vec<InlineQueryResult>) -> Self {
Self {
inline_query_id: query_id.into(),
results,
cache_time: None,
is_personal: None,
next_offset: None,
switch_pm_text: None,
switch_pm_parameter: None,
}
}
pub fn with_cache_time(self, cache_time: u32) -> Self {
Self {
cache_time: Some(cache_time),
..self
}
}
pub fn personal(self) -> Self {
Self {
is_personal: Some(true),
..self
}
}
pub fn with_next_offset(self, offset: impl Into<String>) -> Self {
Self {
next_offset: Some(offset.into()),
..self
}
}
pub fn with_switch_pm_text(self, text: impl Into<String>) -> Self {
Self {
switch_pm_text: Some(text.into()),
..self
}
}
pub fn with_switch_pm_parameter(self, param: impl Into<String>) -> Self {
Self {
switch_pm_parameter: Some(param.into()),
..self
}
}
}
impl TelegramMethod for AnswerInlineQuery {
type Response = bool;
fn name() -> &'static str {
"answerInlineQuery"
}
}
impl JsonMethod for AnswerInlineQuery {}