Merge pull request #29 from teloxide/bot_refactor

Refactor Bot for a bit
This commit is contained in:
Temirkhan Myrzamadi 2020-12-05 05:10:43 +06:00 committed by GitHub
commit 6b2ac7142a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 210 additions and 308 deletions

View file

@ -19,6 +19,8 @@ pub mod cache_me;
#[cfg_attr(all(docsrs, feature = "nightly"), doc(cfg(feature = "throttle")))] #[cfg_attr(all(docsrs, feature = "nightly"), doc(cfg(feature = "throttle")))]
pub mod throttle; pub mod throttle;
mod parse_mode;
#[cfg(feature = "auto_send")] #[cfg(feature = "auto_send")]
#[cfg_attr(all(docsrs, feature = "nightly"), doc(cfg(feature = "auto_send")))] #[cfg_attr(all(docsrs, feature = "nightly"), doc(cfg(feature = "auto_send")))]
pub use auto_send::AutoSend; pub use auto_send::AutoSend;
@ -29,4 +31,6 @@ pub use cache_me::CacheMe;
#[cfg_attr(all(docsrs, feature = "nightly"), doc(cfg(feature = "throttle")))] #[cfg_attr(all(docsrs, feature = "nightly"), doc(cfg(feature = "throttle")))]
pub use throttle::Throttle; pub use throttle::Throttle;
pub use parse_mode::DefaultParseMode;
// FIXME: move default `parse_mode` to adaptor // FIXME: move default `parse_mode` to adaptor

108
src/adaptors/parse_mode.rs Normal file
View file

@ -0,0 +1,108 @@
use crate::{
prelude::Requester,
requests::HasPayload,
types::{ChatId, InputFile, ParseMode, *},
};
/// Default parse mode adaptor, see
/// [`RequesterExt::parse_mode`](crate::requests::RequesterExt::parse_mode)
pub struct DefaultParseMode<B> {
bot: B,
mode: ParseMode,
}
impl<B> DefaultParseMode<B> {
/// Creates new [`DefaultParseMode`]
///
/// Note: it's recommended to use [`RequesterExt::parse_mode`] instead.
///
/// [`RequesterExt::parse_mode`]: crate::requests::RequesterExt::parse_mode
pub fn new(bot: B, parse_mode: ParseMode) -> Self {
Self { bot, mode: parse_mode }
}
/// Allows to access inner bot
pub fn inner(&self) -> &B {
&self.bot
}
/// Unwraps inner bot
pub fn into_inner(self) -> B {
self.bot
}
}
macro_rules! f {
($m:ident $this:ident ($($arg:ident : $T:ty),*)) => {
{
let mut req = $this.inner().$m($($arg),*);
req.payload_mut().parse_mode = Some($this.mode);
req
}
};
}
macro_rules! fty {
($T:ident) => {
B::$T
};
}
macro_rules! fid {
($m:ident $this:ident ($($arg:ident : $T:ty),*)) => {
$this.inner().$m($($arg),*)
};
}
impl<B: Requester> Requester for DefaultParseMode<B> {
type Err = B::Err;
requester_forward! {
send_message,
send_photo,
send_video,
send_audio,
send_document,
send_animation,
send_voice,
edit_message_text,
edit_message_text_inline,
edit_message_caption,
edit_message_caption_inline => f, fty
}
type SendPoll = B::SendPoll;
fn send_poll<C, Q, O>(
&self,
chat_id: C,
question: Q,
options: O,
type_: PollType,
) -> Self::SendPoll
where
C: Into<ChatId>,
Q: Into<String>,
O: IntoIterator<Item = String>,
{
let mut req = self.inner().send_poll(chat_id, question, options, type_);
req.payload_mut().explanation_parse_mode = Some(self.mode);
req
}
requester_forward! {
get_me, get_updates, set_webhook, delete_webhook, get_webhook_info,
forward_message, send_video_note, send_media_group, send_location,
edit_message_live_location, edit_message_live_location_inline, stop_message_live_location,
stop_message_live_location_inline, send_venue, send_contact, send_dice,
send_chat_action, get_user_profile_photos, get_file, kick_chat_member, unban_chat_member,
restrict_chat_member, promote_chat_member, set_chat_administrator_custom_title, set_chat_permissions,
export_chat_invite_link, set_chat_photo, delete_chat_photo, set_chat_title, set_chat_description,
pin_chat_message, unpin_chat_message, leave_chat, get_chat, get_chat_administrators, get_chat_members_count,
get_chat_member, set_chat_sticker_set, delete_chat_sticker_set, answer_callback_query, set_my_commands,
get_my_commands, answer_inline_query, edit_message_media, edit_message_media_inline, edit_message_reply_markup,
edit_message_reply_markup_inline, stop_poll, delete_message, send_sticker, get_sticker_set, upload_sticker_file,
create_new_sticker_set, add_sticker_to_set, set_sticker_position_in_set, delete_sticker_from_set,
set_sticker_set_thumb, send_invoice, answer_shipping_query, answer_pre_checkout_query, set_passport_data_errors => fid, fty
}
}

View file

@ -21,7 +21,7 @@ use crate::{
}, },
types::{ types::{
BotCommand, ChatId, ChatPermissions, InlineQueryResult, InputFile, InputMedia, BotCommand, ChatId, ChatPermissions, InlineQueryResult, InputFile, InputMedia,
InputSticker, LabeledPrice, ParseMode, TargetMessage, InputSticker, LabeledPrice, TargetMessage,
}, },
Bot, Bot,
}; };
@ -119,21 +119,12 @@ impl Bot {
/// - `chat_id`: Unique identifier for the target chat or username of the /// - `chat_id`: Unique identifier for the target chat or username of the
/// target supergroup or channel (in the format `@channelusername`). /// target supergroup or channel (in the format `@channelusername`).
/// - `text`: Text of the message to be sent. /// - `text`: Text of the message to be sent.
///
/// # Notes
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn send_message<C, T>(&self, chat_id: C, text: T) -> SendMessage pub fn send_message<C, T>(&self, chat_id: C, text: T) -> SendMessage
where where
C: Into<ChatId>, C: Into<ChatId>,
T: Into<String>, T: Into<String>,
{ {
self.with_default_parse_mode_if_specified( SendMessage::new(self.clone(), chat_id, text)
SendMessage::new(self.clone(), chat_id, text),
SendMessage::parse_mode,
)
} }
/// Use this method to forward messages of any kind. /// Use this method to forward messages of any kind.
@ -182,20 +173,11 @@ impl Bot {
/// [`InputFile::FileId`]: crate::types::InputFile::FileId /// [`InputFile::FileId`]: crate::types::InputFile::FileId
/// ///
/// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files
///
/// # Notes
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn send_photo<C>(&self, chat_id: C, photo: InputFile) -> SendPhoto pub fn send_photo<C>(&self, chat_id: C, photo: InputFile) -> SendPhoto
where where
C: Into<ChatId>, C: Into<ChatId>,
{ {
self.with_default_parse_mode_if_specified( SendPhoto::new(self.clone(), chat_id, photo)
SendPhoto::new(self.clone(), chat_id, photo),
SendPhoto::parse_mode,
)
} }
/// ///
@ -203,20 +185,11 @@ impl Bot {
/// # Params /// # Params
/// - `chat_id`: Unique identifier for the target chat or username of the /// - `chat_id`: Unique identifier for the target chat or username of the
/// target supergroup or channel (in the format `@channelusername`). /// target supergroup or channel (in the format `@channelusername`).
///
/// # Notes
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn send_audio<C>(&self, chat_id: C, audio: InputFile) -> SendAudio pub fn send_audio<C>(&self, chat_id: C, audio: InputFile) -> SendAudio
where where
C: Into<ChatId>, C: Into<ChatId>,
{ {
self.with_default_parse_mode_if_specified( SendAudio::new(self.clone(), chat_id, audio)
SendAudio::new(self.clone(), chat_id, audio),
SendAudio::parse_mode,
)
} }
/// Use this method to send general files. /// Use this method to send general files.
@ -237,20 +210,11 @@ impl Bot {
/// `multipart/form-data`. [More info on Sending Files »]. /// `multipart/form-data`. [More info on Sending Files »].
/// ///
/// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files
///
/// # Notes
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn send_document<C>(&self, chat_id: C, document: InputFile) -> SendDocument pub fn send_document<C>(&self, chat_id: C, document: InputFile) -> SendDocument
where where
C: Into<ChatId>, C: Into<ChatId>,
{ {
self.with_default_parse_mode_if_specified( SendDocument::new(self.clone(), chat_id, document)
SendDocument::new(self.clone(), chat_id, document),
SendDocument::parse_mode,
)
} }
/// Use this method to send video files, Telegram clients support mp4 videos /// Use this method to send video files, Telegram clients support mp4 videos
@ -274,20 +238,11 @@ impl Bot {
/// [`InputFile::File`]: crate::types::InputFile::File /// [`InputFile::File`]: crate::types::InputFile::File
/// [`InputFile::Url`]: crate::types::InputFile::Url /// [`InputFile::Url`]: crate::types::InputFile::Url
/// [`InputFile::FileId`]: crate::types::InputFile::FileId /// [`InputFile::FileId`]: crate::types::InputFile::FileId
///
/// # Notes
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn send_video<C>(&self, chat_id: C, video: InputFile) -> SendVideo pub fn send_video<C>(&self, chat_id: C, video: InputFile) -> SendVideo
where where
C: Into<ChatId>, C: Into<ChatId>,
{ {
self.with_default_parse_mode_if_specified( SendVideo::new(self.clone(), chat_id, video)
SendVideo::new(self.clone(), chat_id, video),
SendVideo::parse_mode,
)
} }
/// Use this method to send animation files (GIF or H.264/MPEG-4 AVC video /// Use this method to send animation files (GIF or H.264/MPEG-4 AVC video
@ -302,20 +257,11 @@ impl Bot {
/// - `chat_id`: Unique identifier for the target chat or username of the /// - `chat_id`: Unique identifier for the target chat or username of the
/// target supergroup or channel (in the format `@channelusername`). /// target supergroup or channel (in the format `@channelusername`).
/// - `animation`: Animation to send. /// - `animation`: Animation to send.
///
/// # Notes
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn send_animation<C>(&self, chat_id: C, animation: InputFile) -> SendAnimation pub fn send_animation<C>(&self, chat_id: C, animation: InputFile) -> SendAnimation
where where
C: Into<ChatId>, C: Into<ChatId>,
{ {
self.with_default_parse_mode_if_specified( SendAnimation::new(self.clone(), chat_id, animation)
SendAnimation::new(self.clone(), chat_id, animation),
SendAnimation::parse_mode,
)
} }
/// Use this method to send audio files, if you want Telegram clients to /// Use this method to send audio files, if you want Telegram clients to
@ -345,20 +291,11 @@ impl Bot {
/// [`InputFile::Url`]: crate::types::InputFile::Url /// [`InputFile::Url`]: crate::types::InputFile::Url
/// [`InputFile::FileId`]: crate::types::InputFile::FileId /// [`InputFile::FileId`]: crate::types::InputFile::FileId
/// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files /// [More info on Sending Files »]: https://core.telegram.org/bots/api#sending-files
///
/// # Notes
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn send_voice<C>(&self, chat_id: C, voice: InputFile) -> SendVoice pub fn send_voice<C>(&self, chat_id: C, voice: InputFile) -> SendVoice
where where
C: Into<ChatId>, C: Into<ChatId>,
{ {
self.with_default_parse_mode_if_specified( SendVoice::new(self.clone(), chat_id, voice)
SendVoice::new(self.clone(), chat_id, voice),
SendVoice::parse_mode,
)
} }
/// As of [v.4.0], Telegram clients support rounded square mp4 videos of up /// As of [v.4.0], Telegram clients support rounded square mp4 videos of up
@ -567,26 +504,13 @@ impl Bot {
/// - `question`: Poll question, 1-255 characters. /// - `question`: Poll question, 1-255 characters.
/// - `options`: List of answer options, 2-10 strings 1-100 characters /// - `options`: List of answer options, 2-10 strings 1-100 characters
/// each. /// each.
///
/// # Notes
/// Uses [a default parse mode] ([`SendPoll::explanation_parse_mode`]) if
/// specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
/// [`SendPoll::explanation_parse_mode`]:
/// [`SendPoll::explanation_parse_mode`]:
/// crate::types::SendPoll::explanation_parse_mode
pub fn send_poll<C, Q, O>(&self, chat_id: C, question: Q, options: O) -> SendPoll pub fn send_poll<C, Q, O>(&self, chat_id: C, question: Q, options: O) -> SendPoll
where where
C: Into<ChatId>, C: Into<ChatId>,
Q: Into<String>, Q: Into<String>,
O: Into<Vec<String>>, O: Into<Vec<String>>,
{ {
self.with_default_parse_mode_if_specified( SendPoll::new(self.clone(), chat_id, question, options)
SendPoll::new(self.clone(), chat_id, question, options),
SendPoll::explanation_parse_mode,
)
} }
/// Use this method when you need to tell the user that something is /// Use this method when you need to tell the user that something is
@ -1057,24 +981,12 @@ impl Bot {
/// target channel (in the format `@channelusername`). /// target channel (in the format `@channelusername`).
/// - `message_id`: Identifier of the message to edit. /// - `message_id`: Identifier of the message to edit.
/// - `text`: New text of the message. /// - `text`: New text of the message.
///
/// # Notes
///
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn edit_message_text<C, T>(&self, chat_id: C, message_id: i32, text: T) -> EditMessageText pub fn edit_message_text<C, T>(&self, chat_id: C, message_id: i32, text: T) -> EditMessageText
where where
C: Into<ChatId>, C: Into<ChatId>,
T: Into<String>, T: Into<String>,
{ {
match self.parse_mode { EditMessageText::new(self.clone(), chat_id, message_id, text)
None => EditMessageText::new(self.clone(), chat_id, message_id, text),
Some(parse_mode) => {
EditMessageText::new(self.clone(), chat_id, message_id, text).parse_mode(parse_mode)
}
}
} }
/// Use this method to edit text and game messages sent via the bot. /// Use this method to edit text and game messages sent via the bot.
@ -1089,13 +1001,6 @@ impl Bot {
/// ///
/// - `inline_message_id`: Identifier of the inline message. /// - `inline_message_id`: Identifier of the inline message.
/// - `text`: New text of the message. /// - `text`: New text of the message.
///
/// # Notes
///
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn edit_inline_message_text<I, T>( pub fn edit_inline_message_text<I, T>(
&self, &self,
inline_message_id: I, inline_message_id: I,
@ -1105,11 +1010,7 @@ impl Bot {
I: Into<String>, I: Into<String>,
T: Into<String>, T: Into<String>,
{ {
match self.parse_mode { EditInlineMessageText::new(self.clone(), inline_message_id, text)
None => EditInlineMessageText::new(self.clone(), inline_message_id, text),
Some(parse_mode) => EditInlineMessageText::new(self.clone(), inline_message_id, text)
.parse_mode(parse_mode),
}
} }
/// Use this method to edit captions of messages sent via the bot. /// Use this method to edit captions of messages sent via the bot.
@ -1119,23 +1020,11 @@ impl Bot {
/// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). /// [The official docs](https://core.telegram.org/bots/api#editmessagecaption).
/// ///
/// [`True`]: crate::types::True /// [`True`]: crate::types::True
///
/// # Notes
///
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn edit_message_caption<C>(&self, chat_id: C, message_id: i32) -> EditMessageCaption pub fn edit_message_caption<C>(&self, chat_id: C, message_id: i32) -> EditMessageCaption
where where
C: Into<ChatId>, C: Into<ChatId>,
{ {
match self.parse_mode { EditMessageCaption::new(self.clone(), chat_id, message_id)
None => EditMessageCaption::new(self.clone(), chat_id, message_id),
Some(parse_mode) => {
EditMessageCaption::new(self.clone(), chat_id, message_id).parse_mode(parse_mode)
}
}
} }
/// Use this method to edit captions of messages sent via the bot. /// Use this method to edit captions of messages sent via the bot.
@ -1145,21 +1034,11 @@ impl Bot {
/// [The official docs](https://core.telegram.org/bots/api#editmessagecaption). /// [The official docs](https://core.telegram.org/bots/api#editmessagecaption).
/// ///
/// [`True`]: crate::types::True /// [`True`]: crate::types::True
///
/// # Notes
/// Uses [a default parse mode] if specified in [`BotBuilder`].
///
/// [a default parse mode]: crate::BotBuilder::parse_mode
/// [`BotBuilder`]: crate::BotBuilder
pub fn edit_inline_message_caption<I>(&self, inline_message_id: I) -> EditInlineMessageCaption pub fn edit_inline_message_caption<I>(&self, inline_message_id: I) -> EditInlineMessageCaption
where where
I: Into<String>, I: Into<String>,
{ {
match self.parse_mode { EditInlineMessageCaption::new(self.clone(), inline_message_id)
None => EditInlineMessageCaption::new(self.clone(), inline_message_id),
Some(parse_mode) => EditInlineMessageCaption::new(self.clone(), inline_message_id)
.parse_mode(parse_mode),
}
} }
/// Use this method to edit animation, audio, document, photo, or video /// Use this method to edit animation, audio, document, photo, or video
@ -1691,17 +1570,6 @@ impl Bot {
{ {
SetStickerSetThumb::new(self.clone(), name, user_id) SetStickerSetThumb::new(self.clone(), name, user_id)
} }
fn with_default_parse_mode_if_specified<Builder>(
&self,
builder: Builder,
f: fn(Builder, ParseMode) -> Builder,
) -> Builder {
match self.parse_mode {
None => builder,
Some(parse_mode) => f(builder, parse_mode),
}
}
} }
impl Requester for Bot { impl Requester for Bot {

View file

@ -11,7 +11,6 @@ use crate::{
net, net,
requests::{Payload, ResponseResult}, requests::{Payload, ResponseResult},
serde_multipart, serde_multipart,
types::ParseMode,
}; };
mod api; mod api;
@ -31,56 +30,15 @@ pub struct Bot {
token: Arc<str>, token: Arc<str>,
api_url: ApiUrl, api_url: ApiUrl,
client: Client, client: Client,
parse_mode: Option<ParseMode>,
} }
impl Bot { impl Bot {
/// Creates a new `Bot` with the `TELOXIDE_TOKEN` & `TELOXIDE_PROXY`
/// environmental variables (a bot's token & a proxy) and the default
/// [`reqwest::Client`].
///
/// This function passes the value of `TELOXIDE_PROXY` into
/// [`reqwest::Proxy::all`], if it exists, otherwise returns the default
/// client.
///
/// # Panics
/// - If cannot get the `TELOXIDE_TOKEN` environmental variable.
/// - If it cannot create [`reqwest::Client`].
///
/// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html
/// [`reqwest::Proxy::all`]: https://docs.rs/reqwest/latest/reqwest/struct.Proxy.html#method.all
#[must_use]
pub fn from_env() -> Self {
BotBuilder::new().build()
}
/// Creates a new `Bot` with the `TELOXIDE_TOKEN` environmental variable (a
/// bot's token) and your [`reqwest::Client`].
///
/// # Panics
/// If cannot get the `TELOXIDE_TOKEN` environmental variable.
///
/// # Caution
/// Your custom client might not be configured correctly to be able to work
/// in long time durations, see [issue 223].
///
/// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html
/// [issue 223]: https://github.com/teloxide/teloxide/issues/223
#[deprecated]
#[allow(deprecated)]
pub fn from_env_with_client(client: Client) -> Self {
Self::with_client(&get_env(TELOXIDE_TOKEN), client)
}
/// Creates a new `Bot` with the specified token and the default /// Creates a new `Bot` with the specified token and the default
/// [`reqwest::Client`]. /// [http-client](reqwest::Client).
/// ///
/// # Panics /// # Panics
/// If it cannot create [`reqwest::Client`].
/// ///
/// [`reqwest::Client`]: https://docs.rs/reqwest/latest/reqwest/struct.Client.html /// If it cannot create [`reqwest::Client`].
#[deprecated]
#[allow(deprecated)]
pub fn new<S>(token: S) -> Self pub fn new<S>(token: S) -> Self
where where
S: Into<String>, S: Into<String>,
@ -97,8 +55,6 @@ impl Bot {
/// ///
/// [`reqwest::Client`]: https://docs.rs/reqwest/latest/reqwest/struct.Client.html /// [`reqwest::Client`]: https://docs.rs/reqwest/latest/reqwest/struct.Client.html
/// [issue 223]: https://github.com/teloxide/teloxide/issues/223 /// [issue 223]: https://github.com/teloxide/teloxide/issues/223
#[deprecated]
#[allow(deprecated)]
pub fn with_client<S>(token: S, client: Client) -> Self pub fn with_client<S>(token: S, client: Client) -> Self
where where
S: Into<String>, S: Into<String>,
@ -107,9 +63,52 @@ impl Bot {
token: Into::<Arc<str>>::into(Into::<String>::into(token)), token: Into::<Arc<str>>::into(Into::<String>::into(token)),
api_url: ApiUrl::Default, api_url: ApiUrl::Default,
client, client,
parse_mode: None,
} }
} }
/// Creates a new `Bot` with the `TELOXIDE_TOKEN` & `TELOXIDE_PROXY`
/// environmental variables (a bot's token & a proxy) and the default
/// [`reqwest::Client`].
///
/// This function passes the value of `TELOXIDE_PROXY` into
/// [`reqwest::Proxy::all`], if it exists, otherwise returns the default
/// client.
///
/// # Panics
/// - If cannot get the `TELOXIDE_TOKEN` environmental variable.
/// - If it cannot create [`reqwest::Client`].
///
/// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html
/// [`reqwest::Proxy::all`]: https://docs.rs/reqwest/latest/reqwest/struct.Proxy.html#method.all
pub fn from_env() -> Self {
Self::from_env_with_client(crate::client_from_env())
}
/// Creates a new `Bot` with the `TELOXIDE_TOKEN` environmental variable (a
/// bot's token) and your [`reqwest::Client`].
///
/// # Panics
/// If cannot get the `TELOXIDE_TOKEN` environmental variable.
///
/// # Caution
/// Your custom client might not be configured correctly to be able to work
/// in long time durations, see [issue 223].
///
/// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html
/// [issue 223]: https://github.com/teloxide/teloxide/issues/223
pub fn from_env_with_client(client: Client) -> Self {
Self::with_client(&get_env(TELOXIDE_TOKEN), client)
}
/// Returns currently used token
pub fn token(&self) -> &str {
&self.token
}
/// Returns currently used http-client
pub fn client(&self) -> &Client {
&self.client
}
} }
impl Bot { impl Bot {
@ -182,115 +181,3 @@ pub(crate) fn build_sound_bot() -> Client {
fn get_env(env: &'static str) -> String { fn get_env(env: &'static str) -> String {
std::env::var(env).unwrap_or_else(|_| panic!("Cannot get the {} env variable", env)) std::env::var(env).unwrap_or_else(|_| panic!("Cannot get the {} env variable", env))
} }
impl Bot {
pub fn token(&self) -> &str {
&self.token
}
pub fn client(&self) -> &Client {
&self.client
}
}
/// A builder of [`Bot`], supporting some extra settings.
///
/// [`Bot`] crate::Bot
#[derive(Debug, Default)]
pub struct BotBuilder {
token: Option<String>,
client: Option<Client>,
parse_mode: Option<ParseMode>,
}
impl BotBuilder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
/// Specifies a custom HTTPS client. Otherwise, the default will be used.
///
/// # Caution
/// - Your custom client might not be configured correctly to be able to
/// work
/// in long time durations, see [issue 223].
///
/// - If this method is used, the `TELOXIDE_PROXY` environmental variable
/// won't be extracted in [`BotBuilder::build`].
///
/// [issue 223]: https://github.com/teloxide/teloxide/issues/223
/// [`BotBuilder::build`]: crate::BotBuilder::build
#[must_use]
pub fn client(mut self, client: Client) -> Self {
self.client = Some(client);
self
}
/// Specified a custom token.
///
/// Otherwise, a token will be extracted from the `TELOXIDE_TOKEN`
/// environmental variable.
#[must_use]
pub fn token<S>(mut self, token: S) -> Self
where
S: Into<String>,
{
self.token = Some(token.into());
self
}
/// Specifies [`ParseMode`], which will be used during all calls to:
///
/// - [`send_message`]
/// - [`send_photo`]
/// - [`send_video`]
/// - [`send_audio`]
/// - [`send_document`]
/// - [`send_animation`]
/// - [`send_voice`]
/// - [`send_poll`]
/// - [`edit_message_text`]
/// - [`edit_message_caption`]
///
/// [`send_message`]: crate::Bot::send_message
/// [`send_photo`]: crate::Bot::send_photo
/// [`send_video`]: crate::Bot::send_video
/// [`send_audio`]: crate::Bot::send_audio
/// [`send_document`]: crate::Bot::send_document
/// [`send_animation`]: crate::Bot::send_animation
/// [`send_voice`]: crate::Bot::send_voice
/// [`send_poll`]: crate::Bot::send_poll
/// [`edit_message_text`]: crate::Bot::edit_message_text
/// [`edit_message_caption`]: crate::Bot::edit_message_caption
#[must_use]
pub fn parse_mode(mut self, parse_mode: ParseMode) -> Self {
self.parse_mode = Some(parse_mode);
self
}
/// Builds [`Bot`].
///
/// This method will attempt to build a new client with a proxy, specified
/// in the `TELOXIDE_PROXY` (passed into [`reqwest::Proxy::all`])
/// environmental variable, if a client haven't been specified. If
/// `TELOXIDE_PROXY` is unspecified, it'll use no proxy.
///
/// # Panics
/// - If cannot get the `TELOXIDE_TOKEN` environmental variable.
/// - If it cannot create [`reqwest::Client`].
///
/// [`reqwest::Client`]: https://docs.rs/reqwest/0.10.1/reqwest/struct.Client.html
///
/// [`Bot`]: crate::Bot
/// [`reqwest::Proxy::all`]: https://docs.rs/reqwest/latest/reqwest/struct.Proxy.html#method.all
#[must_use]
pub fn build(self) -> Bot {
Bot {
token: self.token.unwrap_or_else(|| get_env(TELOXIDE_TOKEN)).into(),
api_url: ApiUrl::Default,
client: self.client.unwrap_or_else(crate::client_from_env),
parse_mode: self.parse_mode,
}
}
}

View file

@ -7,19 +7,19 @@
// ```console // ```console
// $ RUSTDOCFLAGS="--cfg docsrs" cargo doc --open --all-features // $ RUSTDOCFLAGS="--cfg docsrs" cargo doc --open --all-features
// ``` // ```
#![forbid(unsafe_code)]
#![cfg_attr(all(docsrs, feature = "nightly"), feature(doc_cfg, doc_spotlight))] #![cfg_attr(all(docsrs, feature = "nightly"), feature(doc_cfg, doc_spotlight))]
#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] #![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))]
#![forbid(unsafe_code)]
#![cfg_attr(feature = "full", deny(broken_intra_doc_links))] #![cfg_attr(feature = "full", deny(broken_intra_doc_links))]
//#![deny(missing_docs)] //#![deny(missing_docs)]
#[macro_use]
// The internal helper macros. // The internal helper macros.
#[macro_use]
mod local_macros; mod local_macros;
// FIXME(waffle): rethink modules, find a place for wrappers. // FIXME(waffle): rethink modules, find a place for wrappers.
pub use self::{ pub use self::{
bot::{Bot, BotBuilder}, bot::Bot,
errors::{ApiError, DownloadError, RequestError}, errors::{ApiError, DownloadError, RequestError},
}; };

View file

@ -1,4 +1,4 @@
use crate::requests::Requester; use crate::{adaptors::DefaultParseMode, requests::Requester, types::ParseMode};
#[cfg(feature = "cache_me")] #[cfg(feature = "cache_me")]
use crate::adaptors::CacheMe; use crate::adaptors::CacheMe;
@ -46,6 +46,41 @@ pub trait RequesterExt: Requester {
{ {
Throttle::new_spawn(self, limits) Throttle::new_spawn(self, limits)
} }
/// Specifies default [`ParseMode`], which will be used during all calls to:
///
/// - [`send_message`]
/// - [`send_photo`]
/// - [`send_video`]
/// - [`send_audio`]
/// - [`send_document`]
/// - [`send_animation`]
/// - [`send_voice`]
/// - [`send_poll`]
/// - [`edit_message_text`] (and [`edit_message_text_inline`])
/// - [`edit_message_caption`] (and [`edit_message_caption_inline`])
///
/// [`send_message`]: crate::requests::Requester::send_message
/// [`send_photo`]: crate::requests::Requester::send_photo
/// [`send_video`]: crate::requests::Requester::send_video
/// [`send_audio`]: crate::requests::Requester::send_audio
/// [`send_document`]: crate::requests::Requester::send_document
/// [`send_animation`]: crate::requests::Requester::send_animation
/// [`send_voice`]: crate::requests::Requester::send_voice
/// [`send_poll`]: crate::requests::Requester::send_poll
/// [`edit_message_text`]: crate::requests::Requester::edit_message_text
/// [`edit_message_text_inline`]:
/// crate::requests::Requester::edit_message_text_inline
/// [`edit_message_caption`]:
/// crate::requests::Requester::edit_message_caption
/// [`edit_message_caption_inline`]:
/// crate::requests::Requester::edit_message_caption_inline
fn parse_mode(self, parse_mode: ParseMode) -> DefaultParseMode<Self>
where
Self: Sized,
{
DefaultParseMode::new(self, parse_mode)
}
} }
impl<T> RequesterExt for T impl<T> RequesterExt for T