use super::{session::base::Session, Reqwest};
use crate::{errors::SessionErrorKind, methods::TelegramMethod, utils::token};
use std::{
env,
fmt::{self, Debug, Display, Formatter},
};
#[derive(Clone, Default)]
pub struct Bot<Client = Reqwest> {
pub token: String,
pub hidden_token: String,
pub id: i64,
client: Client,
}
impl<Client> Bot<Client> {
#[must_use]
pub fn with_client(token: impl Into<String>, client: Client) -> Self {
let token = token.into();
let id = token::extract_bot_id(&token).expect(
"This bot token is invalid, please check it. If you test your bot, and you don't have \
a token, use `Bot::default` method instead of `Bot::new`.",
);
let hidden_token = token::hide(&token);
Self {
token,
hidden_token,
id,
client,
}
}
}
impl Bot<Reqwest> {
#[must_use]
pub fn new(token: impl Into<String>) -> Self {
Self::with_client(token, Reqwest::default())
}
#[must_use]
pub fn from_env_by_key(name: impl AsRef<str>) -> Self {
Self::new(env::var(name.as_ref()).expect("This env variable is not set!"))
}
#[must_use]
pub fn from_env() -> Self {
Self::from_env_by_key("BOT_TOKEN")
}
}
impl<Client> Debug for Bot<Client> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Bot")
.field("token", &self.hidden_token)
.field("bot_id", &self.id)
.finish_non_exhaustive()
}
}
impl<Client> Display for Bot<Client> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"Bot {{ bot_id: {}, token: {} }}",
self.id, self.hidden_token,
)
}
}
impl<Client: Session> Bot<Client> {
pub async fn send<T>(&self, method: T) -> Result<T::Return, SessionErrorKind>
where
T: TelegramMethod + Send + Sync,
T::Method: Send + Sync,
{
self.client
.make_request_and_get_result(self, method, None)
.await
}
pub async fn send_with_timeout<T>(
&self,
method: T,
request_timeout: f32,
) -> Result<T::Return, SessionErrorKind>
where
T: TelegramMethod + Send + Sync,
T::Method: Send + Sync,
{
self.client
.make_request_and_get_result(self, method, Some(request_timeout))
.await
}
}