use std::error::Error as StdError;
use std::ops::Not;
use hyper::Body;
use hyper_multipart_rfc7578::client::multipart;
use hyper_multipart_rfc7578::client::multipart::Form;
use serde::{Serialize, Serializer};
use serde_json::Value;
pub use answer_callback_query::*;
pub use delete_chat_photo::*;
pub use delete_chat_sticker_set::*;
pub use delete_message::*;
pub use edit_live_location::*;
pub use edit_message_caption::*;
pub use edit_message_media::*;
pub use edit_message_reply_markup::*;
pub use edit_message_text::*;
pub use export_chat_invite_link::*;
pub use forward_message::*;
pub use get_chat::*;
pub use get_chat_administrators::*;
pub use get_chat_member::*;
pub use get_chat_members_count::*;
pub use get_file::*;
pub use get_me::*;
pub use get_updates::*;
pub use get_user_profile_photos::*;
pub use kick_chat_member::*;
pub use leave_chat::*;
pub use pin_chat_message::*;
pub use promote_chat_member::*;
pub use restrict_chat_member::*;
pub use send_animation::*;
pub use send_audio::*;
pub use send_chat_action::*;
pub use send_contact::*;
pub use send_document::*;
pub use send_location::*;
pub use send_media_group::*;
pub use send_message::*;
pub use send_photo::*;
pub use send_poll::*;
pub use send_venue::*;
pub use send_video::*;
pub use send_video_note::*;
pub use send_voice::*;
pub use set_chat_description::*;
pub use set_chat_photo::*;
pub use set_chat_sticker_set::*;
pub use set_chat_title::*;
pub use stop_live_location::*;
pub use stop_poll::*;
pub use unban_chat_member::*;
pub use unpin_chat_message::*;
use crate::error::Error;
use std::io::Cursor;
mod answer_callback_query;
mod delete_chat_photo;
mod delete_chat_sticker_set;
mod delete_message;
mod edit_live_location;
mod edit_message_caption;
mod edit_message_media;
mod edit_message_reply_markup;
mod edit_message_text;
mod export_chat_invite_link;
mod forward_message;
mod get_chat;
mod get_chat_administrators;
mod get_chat_member;
mod get_chat_members_count;
mod get_file;
mod get_me;
mod get_updates;
mod get_user_profile_photos;
mod kick_chat_member;
mod leave_chat;
mod pin_chat_message;
mod promote_chat_member;
mod restrict_chat_member;
mod send_animation;
mod send_audio;
mod send_chat_action;
mod send_contact;
mod send_document;
mod send_location;
mod send_media_group;
mod send_message;
mod send_photo;
mod send_poll;
mod send_venue;
mod send_video;
mod send_video_note;
mod send_voice;
mod set_chat_description;
mod set_chat_photo;
mod set_chat_sticker_set;
mod set_chat_title;
mod stop_live_location;
mod stop_poll;
mod unban_chat_member;
mod unpin_chat_message;
pub trait Request: Serialize + Sized {
type ResponseType;
fn method(&self) -> &'static str;
fn set_http_request_body(
self,
request_builder: hyper::http::request::Builder,
) -> Result<hyper::http::request::Request<Body>, Error> {
add_json_body(request_builder, &self)
}
}
pub(crate) fn add_json_body<S: Serialize + Sized>(
mut request_builder: hyper::http::request::Builder,
serializable: &S,
) -> Result<hyper::http::request::Request<Body>, Error> {
let json_bytes = serde_json::to_vec(serializable).map_err(Error::Serde)?;
request_builder
.header("content-type", "application/json")
.body(Body::from(json_bytes))
.map_err(|x| Error::RequestBuild(x.description().to_string()))
}
pub(crate) fn add_form_body(
mut request_builder: hyper::http::request::Builder,
form: Form<'static>,
) -> Result<hyper::http::request::Request<Body>, Error> {
form.set_body_convert::<hyper::Body, multipart::Body>(&mut request_builder)
.map_err(|x| Error::RequestBuild(x.description().to_string()))
}
pub(crate) fn add_file_to_form(form: &mut Form, file: FileKind, upload_type: Option<&str>) {
if let FileKind::InputFile {
name,
content,
thumb,
} = file
{
form.add_reader_file(upload_type.unwrap_or(name), Cursor::new(content), name);
if let Some(thumb) = thumb {
let thumb_name = format!("thumb_{}", name);
form.add_reader_file(&thumb_name, Cursor::new(thumb), thumb_name.as_str());
form.add_text("thumb", format!("attach://{}", &thumb_name));
}
}
}
pub(crate) fn add_fields_to_form<S: Serialize + Sized>(
form: &mut Form<'static>,
serializable: &S,
) -> Result<(), Error> {
let json = serde_json::to_value(serializable).map_err(Error::Serde)?;
if let Value::Object(map) = json {
for (k, v) in map {
match v {
Value::String(s) => form.add_text(k, s),
other => form.add_text(k, other.to_string()),
}
}
}
Ok(())
}
#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum FileKind<'a> {
FileId(&'a str),
Url(&'a str),
#[serde(serialize_with = "FileKind::serialize_attach")]
InputFile {
name: &'a str,
content: Vec<u8>,
thumb: Option<Vec<u8>>,
},
}
impl<'a> FileKind<'a> {
pub(crate) fn is_input_file(&self) -> bool {
if let FileKind::InputFile { .. } = &self {
true
} else {
false
}
}
pub(crate) fn serialize_attach<S: Serializer>(
field0: &str,
_: &[u8],
_: &Option<Vec<u8>>,
s: S,
) -> Result<S::Ok, S::Error> {
s.serialize_str(&format!("attach://{}", field0))
}
}
#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum ChatId<'a> {
Id(i64),
Username(&'a str),
}
impl<'a> From<i64> for ChatId<'a> {
fn from(x: i64) -> Self {
ChatId::Id(x)
}
}
impl<'a> From<&'a str> for ChatId<'a> {
fn from(x: &'a str) -> Self {
ChatId::Username(x)
}
}
#[derive(Serialize, Debug, Clone)]
pub struct InputMediaPhoto<'a> {
pub media: FileKind<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub caption: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parse_mode: Option<ParseMode>,
}
impl<'a> InputMediaPhoto<'a> {
pub fn new(media: FileKind<'a>) -> Self {
Self {
media,
caption: None,
parse_mode: None,
}
}
}
#[derive(Serialize, Debug, Clone)]
pub struct InputMediaVideo<'a> {
pub media: FileKind<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub caption: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parse_mode: Option<ParseMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub width: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub height: Option<i64>,
#[serde(skip_serializing_if = "Not::not")]
pub supports_streaming: bool,
}
impl<'a> InputMediaVideo<'a> {
pub fn new(media: FileKind<'a>) -> Self {
Self {
media,
caption: None,
parse_mode: None,
duration: None,
width: None,
height: None,
supports_streaming: false,
}
}
}
#[derive(Serialize, Debug, Clone)]
pub struct InputMediaAnimation<'a> {
pub media: FileKind<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub caption: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parse_mode: Option<ParseMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub width: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub height: Option<i64>,
}
impl<'a> InputMediaAnimation<'a> {
pub fn new(media: FileKind<'a>) -> Self {
Self {
media,
caption: None,
parse_mode: None,
duration: None,
width: None,
height: None,
}
}
}
#[derive(Serialize, Debug, Clone)]
pub struct InputMediaDocument<'a> {
pub media: FileKind<'a>,
#[serde(skip_serializing_if = "Option::is_none")]
pub caption: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parse_mode: Option<ParseMode>,
}
impl<'a> InputMediaDocument<'a> {
pub fn new(media: FileKind<'a>) -> Self {
Self {
media,
caption: None,
parse_mode: None,
}
}
}
#[derive(Serialize, Debug, Clone)]
pub struct InputMediaAudio<'a> {
pub media: FileKind<'a>,
#[serde(skip_serializing)]
pub thumb: Option<Vec<u8>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub caption: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parse_mode: Option<ParseMode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub duration: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub performer: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<&'a str>,
}
impl<'a> InputMediaAudio<'a> {
pub fn new(media: FileKind<'a>) -> Self {
Self {
media,
thumb: None,
caption: None,
parse_mode: None,
duration: None,
performer: None,
title: None,
}
}
}
#[derive(Serialize, Debug, Clone)]
#[serde(tag = "type")]
pub enum InputMedia<'a> {
#[serde(rename = "video")]
Video(InputMediaVideo<'a>),
#[serde(rename = "photo")]
Photo(InputMediaPhoto<'a>),
#[serde(rename = "animation")]
Animation(InputMediaAnimation<'a>),
#[serde(rename = "document")]
Document(InputMediaDocument<'a>),
#[serde(rename = "audio")]
Audio(InputMediaAudio<'a>),
}
impl<'a> InputMedia<'a> {
fn get_file(self) -> FileKind<'a> {
match self {
InputMedia::Photo(x) => x.media,
InputMedia::Video(x) => x.media,
InputMedia::Animation(x) => x.media,
InputMedia::Document(x) => x.media,
InputMedia::Audio(x) => x.media,
}
}
fn contains_input_file(&self) -> bool {
match &self {
InputMedia::Video(x) => x.media.is_input_file(),
InputMedia::Photo(x) => x.media.is_input_file(),
InputMedia::Animation(x) => x.media.is_input_file(),
InputMedia::Document(x) => x.media.is_input_file(),
InputMedia::Audio(x) => x.media.is_input_file(),
}
}
}
#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum ReplyMarkup<'a> {
InlineKeyboard(InlineKeyboard<'a>),
ReplyKeyboardMarkup(ReplyKeyboardMarkup<'a>),
ReplyKeyboardRemove(ReplyKeyboardRemove),
ForceReply(ForceReply),
}
#[derive(Serialize, Debug, Clone)]
pub struct InlineKeyboard<'a> {
pub inline_keyboard: &'a [Vec<InlineKeyboardButton<'a>>],
}
#[derive(Serialize, Debug, Clone)]
pub struct ReplyKeyboardMarkup<'a> {
pub keyboard: &'a [Vec<KeyboardButton<'a>>],
#[serde(skip_serializing_if = "Not::not")]
pub resize_keyboard: bool,
#[serde(skip_serializing_if = "Not::not")]
pub one_time_keyboard: bool,
#[serde(skip_serializing_if = "Not::not")]
pub selective: bool,
}
#[derive(Serialize, Debug, Clone)]
pub struct ReplyKeyboardRemove {
#[serde(skip_serializing_if = "Not::not")]
pub remove_keyboard: bool,
#[serde(skip_serializing_if = "Not::not")]
pub selective: bool,
}
#[derive(Serialize, Debug, Clone)]
pub struct ForceReply {
#[serde(skip_serializing_if = "Not::not")]
pub force_reply: bool,
#[serde(skip_serializing_if = "Not::not")]
pub selective: bool,
}
#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum InlineKeyboardButton<'a> {
Url {
text: &'a str,
url: &'a str,
},
CallbackData {
text: &'a str,
callback_data: &'a str,
},
}
#[derive(Serialize, Debug, Clone)]
#[serde(untagged)]
pub enum KeyboardButton<'a> {
Text(&'a str),
}
#[derive(Serialize, Debug, Clone, Copy)]
pub enum ParseMode {
Html,
Markdown,
}
#[serde(untagged)]
#[derive(Serialize, Debug, Clone)]
pub enum MessageOrInlineMessageId<'a> {
Inline {
inline_message_id: &'a str,
},
Chat {
chat_id: ChatId<'a>,
message_id: i64,
},
}