mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-11 04:21:12 +01:00
Format the sources
This commit is contained in:
parent
4ce7ceb831
commit
9b8f180a8a
43 changed files with 519 additions and 402 deletions
|
@ -1,15 +1,15 @@
|
|||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
requests::{
|
||||
AnswerPreCheckoutQuery, AnswerShippingQuery, EditMessageLiveLocation,
|
||||
ForwardMessage, GetFile, GetMe, KickChatMember, PinChatMessage,
|
||||
PromoteChatMember, RestrictChatMember, SendAudio, SendChatAction,
|
||||
SendContact, SendLocation, SendMediaGroup, SendMessage, SendPhoto,
|
||||
SendPoll, SendVenue, SendVideoNote, SendVoice, StopMessageLiveLocation,
|
||||
UnbanChatMember, UnpinChatMessage, GetUpdates
|
||||
ForwardMessage, GetFile, GetMe, GetUpdates, KickChatMember,
|
||||
PinChatMessage, PromoteChatMember, RestrictChatMember, SendAudio,
|
||||
SendChatAction, SendContact, SendLocation, SendMediaGroup, SendMessage,
|
||||
SendPhoto, SendPoll, SendVenue, SendVideoNote, SendVoice,
|
||||
StopMessageLiveLocation, UnbanChatMember, UnpinChatMessage,
|
||||
},
|
||||
types::{ChatAction, ChatId, ChatPermissions, InputFile, InputMedia},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Telegram functions
|
||||
impl Bot {
|
||||
|
|
|
@ -3,10 +3,10 @@ use tokio::io::AsyncWrite;
|
|||
#[cfg(feature = "unstable-stream")]
|
||||
use ::{bytes::Bytes, tokio::stream::Stream};
|
||||
|
||||
use crate::bot::Bot;
|
||||
#[cfg(feature = "unstable-stream")]
|
||||
use crate::network::download_file_stream;
|
||||
use crate::{network::download_file, DownloadError};
|
||||
use crate::bot::Bot;
|
||||
|
||||
impl Bot {
|
||||
/// Download file from telegram into `destination`.
|
||||
|
@ -17,9 +17,7 @@ impl Bot {
|
|||
/// ## Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use telebofr::{
|
||||
/// bot:: requests::Request, types::File as TgFile,
|
||||
/// };
|
||||
/// use telebofr::{bot::requests::Request, types::File as TgFile};
|
||||
/// use tokio::fs::File;
|
||||
/// # use telebofr::RequestError;
|
||||
///
|
||||
|
|
|
@ -28,7 +28,9 @@ impl<T, F: Fn(&T) -> bool> Filter<T> for F {
|
|||
/// assert_eq!(false.test(&()), false);
|
||||
/// ```
|
||||
impl<T> Filter<T> for bool {
|
||||
fn test(&self, _: &T) -> bool { *self }
|
||||
fn test(&self, _: &T) -> bool {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
/// And filter.
|
||||
|
@ -82,7 +84,6 @@ pub fn and<A, B>(a: A, b: B) -> And<A, B> {
|
|||
And::new(a, b)
|
||||
}
|
||||
|
||||
|
||||
/// Or filter.
|
||||
///
|
||||
/// Passes if at least one underlying filters passes.
|
||||
|
@ -92,7 +93,7 @@ pub fn and<A, B>(a: A, b: B) -> And<A, B> {
|
|||
///
|
||||
/// ## Examples
|
||||
/// ```
|
||||
/// use telebofr::dispatcher::filter::{Or, Filter};
|
||||
/// use telebofr::dispatcher::filter::{Filter, Or};
|
||||
///
|
||||
/// // Note: bool can be treated as `Filter` that always return self.
|
||||
/// assert!(Or::new(true, false).test(&()));
|
||||
|
@ -134,14 +135,13 @@ pub fn or<A, B>(a: A, b: B) -> Or<A, B> {
|
|||
Or::new(a, b)
|
||||
}
|
||||
|
||||
|
||||
/// Not filter.
|
||||
///
|
||||
/// Passes if underlying filter don't pass.
|
||||
///
|
||||
/// ## Examples
|
||||
/// ```
|
||||
/// use telebofr::dispatcher::filter::{Not, Filter};
|
||||
/// use telebofr::dispatcher::filter::{Filter, Not};
|
||||
///
|
||||
/// // Note: bool can be treated as `Filter` that always return self.
|
||||
/// assert!(Not::new(false).test(&()));
|
||||
|
@ -242,12 +242,11 @@ macro_rules! any {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
/// Simple wrapper around `Filter` that adds `|` and `&` operators.
|
||||
///
|
||||
/// ## Examples
|
||||
/// ```
|
||||
/// use telebofr::dispatcher::filter::{Filter, f, F, And, Or};
|
||||
/// use telebofr::dispatcher::filter::{f, And, Filter, Or, F};
|
||||
///
|
||||
/// let flt1 = |i: &i32| -> bool { *i > 17 };
|
||||
/// let flt2 = |i: &i32| -> bool { *i < 42 };
|
||||
|
@ -259,7 +258,6 @@ macro_rules! any {
|
|||
/// assert_eq!(and.test(&50), false); // `flt2` doesn't pass
|
||||
/// assert_eq!(and.test(&16), false); // `flt1` doesn't pass
|
||||
///
|
||||
///
|
||||
/// let or = f(flt1) | flt3;
|
||||
/// assert!(or.test(&19)); // `flt1` passes
|
||||
/// assert!(or.test(&16)); // `flt2` passes
|
||||
|
@ -267,9 +265,8 @@ macro_rules! any {
|
|||
///
|
||||
/// assert_eq!(or.test(&17), false); // both don't pass
|
||||
///
|
||||
///
|
||||
/// // Note: only first filter in chain should be wrapped in `f(...)`
|
||||
/// let complicated: F<Or<And<_, _>, _>>= f(flt1) & flt2 | flt3;
|
||||
/// let complicated: F<Or<And<_, _>, _>> = f(flt1) & flt2 | flt3;
|
||||
/// assert!(complicated.test(&2)); // `flt3` passes
|
||||
/// assert!(complicated.test(&21)); // `flt1` and `flt2` pass
|
||||
///
|
||||
|
@ -287,7 +284,7 @@ pub fn f<A>(a: A) -> F<A> {
|
|||
|
||||
impl<T, A> Filter<T> for F<A>
|
||||
where
|
||||
A: Filter<T>
|
||||
A: Filter<T>,
|
||||
{
|
||||
fn test(&self, value: &T) -> bool {
|
||||
self.0.test(value)
|
||||
|
@ -310,8 +307,9 @@ impl<A, B> std::ops::BitOr<B> for F<A> {
|
|||
}
|
||||
}
|
||||
|
||||
/* workaround for `E0207` compiler error */
|
||||
/// Extensions for filters
|
||||
pub trait FilterExt<T /* workaround for `E0207` compiler error */> {
|
||||
pub trait FilterExt<T> {
|
||||
/// Alias for [`Not::new`]
|
||||
///
|
||||
/// ## Examples
|
||||
|
@ -325,7 +323,10 @@ pub trait FilterExt<T /* workaround for `E0207` compiler error */> {
|
|||
/// ```
|
||||
///
|
||||
/// [`Not::new`]: crate::dispatcher::filter::Not::new
|
||||
fn not(self) -> Not<Self> where Self: Sized {
|
||||
fn not(self) -> Not<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Not::new(self)
|
||||
}
|
||||
|
||||
|
@ -344,7 +345,10 @@ pub trait FilterExt<T /* workaround for `E0207` compiler error */> {
|
|||
/// ```
|
||||
///
|
||||
/// [`Not::new`]: crate::dispatcher::filter::And::new
|
||||
fn and<B>(self, other: B) -> And<Self, B> where Self: Sized {
|
||||
fn and<B>(self, other: B) -> And<Self, B>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
And::new(self, other)
|
||||
}
|
||||
|
||||
|
@ -363,7 +367,10 @@ pub trait FilterExt<T /* workaround for `E0207` compiler error */> {
|
|||
/// ```
|
||||
///
|
||||
/// [`Not::new`]: crate::dispatcher::filter::Or::new
|
||||
fn or<B>(self, other: B) -> Or<Self, B> where Self: Sized {
|
||||
fn or<B>(self, other: B) -> Or<Self, B>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
Or::new(self, other)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
use futures::FutureExt;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
use futures::FutureExt;
|
||||
|
||||
pub type HandlerResult<E> = Result<(), E>;
|
||||
|
||||
/// Asynchronous handler for event `T` (like `&self, I -> Future` fn)
|
||||
pub trait Handler<'a, T, E> {
|
||||
fn handle(&self, value: T) -> Pin<Box<dyn Future<Output = HandlerResult<E>> + 'a>>;
|
||||
fn handle(
|
||||
&self,
|
||||
value: T,
|
||||
) -> Pin<Box<dyn Future<Output = HandlerResult<E>> + 'a>>;
|
||||
}
|
||||
|
||||
pub trait IntoHandlerResult<E> {
|
||||
|
@ -32,7 +36,10 @@ where
|
|||
R: IntoHandlerResult<E> + 'a,
|
||||
E: 'a,
|
||||
{
|
||||
fn handle(&self, value: T) -> Pin<Box<dyn Future<Output = HandlerResult<E>> + 'a>> {
|
||||
fn handle(
|
||||
&self,
|
||||
value: T,
|
||||
) -> Pin<Box<dyn Future<Output = HandlerResult<E>> + 'a>> {
|
||||
Box::pin(self(value).map(IntoHandlerResult::into_hr))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
//! Update dispatching.
|
||||
|
||||
use async_trait::async_trait;
|
||||
pub use filter::Filter;
|
||||
pub use handler::Handler;
|
||||
|
||||
pub mod filter;
|
||||
pub mod handler;
|
||||
pub mod simple;
|
||||
pub mod updater;
|
||||
|
||||
pub use filter::Filter;
|
||||
pub use handler::Handler;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait(?Send)]
|
||||
#[async_trait(? Send)]
|
||||
pub trait Dispatcher<'a, U> {
|
||||
async fn dispatch(&'a mut self, updater: U);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::pin::Pin;
|
||||
use std::future::Future;
|
||||
use std::fmt::Debug;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
// TODO: shouldn't it be trait?
|
||||
pub enum ErrorPolicy<'a, E> {
|
||||
|
@ -15,14 +15,12 @@ where
|
|||
{
|
||||
pub async fn handle_error(&self, error: E) {
|
||||
match self {
|
||||
Self::Ignore => {},
|
||||
Self::Ignore => {}
|
||||
Self::Log => {
|
||||
// TODO: better message
|
||||
log::error!("Error in handler: {:?}", error)
|
||||
}
|
||||
Self::Custom(func) => {
|
||||
func(error).await
|
||||
}
|
||||
Self::Custom(func) => func(error).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,4 +31,4 @@ where
|
|||
{
|
||||
Self::Custom(Box::new(move |e| Box::pin(f(e))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,19 @@
|
|||
pub mod error_policy;
|
||||
|
||||
use futures::StreamExt;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
dispatcher::{
|
||||
filter::Filter,
|
||||
handler::Handler,
|
||||
filter::Filter, handler::Handler, simple::error_policy::ErrorPolicy,
|
||||
updater::Updater,
|
||||
simple::error_policy::ErrorPolicy,
|
||||
},
|
||||
types::{
|
||||
Update,
|
||||
Message,
|
||||
UpdateKind,
|
||||
CallbackQuery,
|
||||
ChosenInlineResult,
|
||||
},
|
||||
types::{CallbackQuery, ChosenInlineResult, Message, Update, UpdateKind},
|
||||
};
|
||||
|
||||
type Handlers<'a, T, E> = Vec<(Box<dyn Filter<T> + 'a>, Box<dyn Handler<'a, T, E> + 'a>)>;
|
||||
pub mod error_policy;
|
||||
|
||||
type Handlers<'a, T, E> =
|
||||
Vec<(Box<dyn Filter<T> + 'a>, Box<dyn Handler<'a, T, E> + 'a>)>;
|
||||
|
||||
/// Dispatcher that dispatches updates from telegram.
|
||||
///
|
||||
|
@ -29,10 +23,10 @@ type Handlers<'a, T, E> = Vec<(Box<dyn Filter<T> + 'a>, Box<dyn Handler<'a, T, E
|
|||
/// - Handler's fututres are also boxed
|
||||
/// - [Custom error policy] is also boxed
|
||||
/// - All errors from [updater] are ignored (TODO: remove this limitation)
|
||||
/// - All handlers executed in order (this means that in dispatcher have
|
||||
/// 2 upadtes it will first execute some handler into complition with
|
||||
/// first update and **then** search for handler for second update,
|
||||
/// this is probably wrong)
|
||||
/// - All handlers executed in order (this means that in dispatcher have 2
|
||||
/// upadtes it will first execute some handler into complition with first
|
||||
/// update and **then** search for handler for second update, this is probably
|
||||
/// wrong)
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
|
@ -41,11 +35,10 @@ type Handlers<'a, T, E> = Vec<(Box<dyn Filter<T> + 'a>, Box<dyn Handler<'a, T, E
|
|||
/// # async fn run() {
|
||||
/// use std::convert::Infallible;
|
||||
/// use telebofr::{
|
||||
/// bot::
|
||||
/// types::Message,
|
||||
/// bot::types::Message,
|
||||
/// dispatcher::{
|
||||
/// simple::{error_policy::ErrorPolicy, Dispatcher},
|
||||
/// updater::polling,
|
||||
/// simple::{Dispatcher, error_policy::ErrorPolicy},
|
||||
/// },
|
||||
/// };
|
||||
///
|
||||
|
@ -59,8 +52,8 @@ type Handlers<'a, T, E> = Vec<(Box<dyn Filter<T> + 'a>, Box<dyn Handler<'a, T, E
|
|||
/// // with error policy that just ignores all errors (that can't ever happen)
|
||||
/// let mut dp = Dispatcher::<Infallible>::new(ErrorPolicy::Ignore)
|
||||
/// // Add 'handler' that will handle all messages sent to the bot
|
||||
/// .message_handler(true, |mes: Message| async move {
|
||||
/// println!("New message: {:?}", mes)
|
||||
/// .message_handler(true, |mes: Message| {
|
||||
/// async move { println!("New message: {:?}", mes) }
|
||||
/// })
|
||||
/// // Add 'handler' that will handle all
|
||||
/// // messages edited in chat with the bot
|
||||
|
@ -72,8 +65,9 @@ type Handlers<'a, T, E> = Vec<(Box<dyn Filter<T> + 'a>, Box<dyn Handler<'a, T, E
|
|||
/// ```
|
||||
///
|
||||
/// [`std::fmt::Debug`]: std::fmt::Debug
|
||||
/// [Custom error policy]: crate::dispatcher::simple::error_policy::ErrorPolicy::Custom
|
||||
/// [updater]: crate::dispatcher::updater
|
||||
/// [Custom error policy]:
|
||||
/// crate::dispatcher::simple::error_policy::ErrorPolicy::Custom [updater]:
|
||||
/// crate::dispatcher::updater
|
||||
pub struct Dispatcher<'a, E> {
|
||||
message_handlers: Handlers<'a, Message, E>,
|
||||
edited_message_handlers: Handlers<'a, Message, E>,
|
||||
|
@ -98,7 +92,7 @@ where
|
|||
inline_query_handlers: Vec::new(),
|
||||
chosen_inline_result_handlers: Vec::new(),
|
||||
callback_query_handlers: Vec::new(),
|
||||
error_policy
|
||||
error_policy,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +101,8 @@ where
|
|||
F: Filter<Message> + 'a,
|
||||
H: Handler<'a, Message, E> + 'a,
|
||||
{
|
||||
self.message_handlers.push((Box::new(filter), Box::new(handler)));
|
||||
self.message_handlers
|
||||
.push((Box::new(filter), Box::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -116,7 +111,8 @@ where
|
|||
F: Filter<Message> + 'a,
|
||||
H: Handler<'a, Message, E> + 'a,
|
||||
{
|
||||
self.edited_message_handlers.push((Box::new(filter), Box::new(handler)));
|
||||
self.edited_message_handlers
|
||||
.push((Box::new(filter), Box::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -125,16 +121,22 @@ where
|
|||
F: Filter<Message> + 'a,
|
||||
H: Handler<'a, Message, E> + 'a,
|
||||
{
|
||||
self.channel_post_handlers.push((Box::new(filter), Box::new(handler)));
|
||||
self.channel_post_handlers
|
||||
.push((Box::new(filter), Box::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn edited_channel_post_handler<F, H>(mut self, filter: F, handler: H) -> Self
|
||||
pub fn edited_channel_post_handler<F, H>(
|
||||
mut self,
|
||||
filter: F,
|
||||
handler: H,
|
||||
) -> Self
|
||||
where
|
||||
F: Filter<Message> + 'a,
|
||||
H: Handler<'a, Message, E> + 'a,
|
||||
{
|
||||
self.edited_channel_post_handlers.push((Box::new(filter), Box::new(handler)));
|
||||
self.edited_channel_post_handlers
|
||||
.push((Box::new(filter), Box::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -143,16 +145,22 @@ where
|
|||
F: Filter<()> + 'a,
|
||||
H: Handler<'a, (), E> + 'a,
|
||||
{
|
||||
self.inline_query_handlers.push((Box::new(filter), Box::new(handler)));
|
||||
self.inline_query_handlers
|
||||
.push((Box::new(filter), Box::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn chosen_inline_result_handler<F, H>(mut self, filter: F, handler: H) -> Self
|
||||
pub fn chosen_inline_result_handler<F, H>(
|
||||
mut self,
|
||||
filter: F,
|
||||
handler: H,
|
||||
) -> Self
|
||||
where
|
||||
F: Filter<ChosenInlineResult> + 'a,
|
||||
H: Handler<'a, ChosenInlineResult, E> + 'a,
|
||||
{
|
||||
self.chosen_inline_result_handlers.push((Box::new(filter), Box::new(handler)));
|
||||
self.chosen_inline_result_handlers
|
||||
.push((Box::new(filter), Box::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -161,65 +169,91 @@ where
|
|||
F: Filter<CallbackQuery> + 'a,
|
||||
H: Handler<'a, CallbackQuery, E> + 'a,
|
||||
{
|
||||
self.callback_query_handlers.push((Box::new(filter), Box::new(handler)));
|
||||
self.callback_query_handlers
|
||||
.push((Box::new(filter), Box::new(handler)));
|
||||
self
|
||||
}
|
||||
|
||||
// TODO: Can someone simplify this?
|
||||
pub async fn dispatch<U>(&mut self, updates: U)
|
||||
where
|
||||
U: Updater + 'a
|
||||
U: Updater + 'a,
|
||||
{
|
||||
updates.for_each(|res| {
|
||||
async {
|
||||
let res = res;
|
||||
let Update { kind, id } = match res {
|
||||
Ok(upd) => upd,
|
||||
_ => return // TODO: proper error handling
|
||||
};
|
||||
updates
|
||||
.for_each(|res| {
|
||||
async {
|
||||
let res = res;
|
||||
let Update { kind, id } = match res {
|
||||
Ok(upd) => upd,
|
||||
_ => return, // TODO: proper error handling
|
||||
};
|
||||
|
||||
log::debug!("Handled update#{id:?}: {kind:?}", id = id, kind = kind);
|
||||
log::debug!(
|
||||
"Handled update#{id:?}: {kind:?}",
|
||||
id = id,
|
||||
kind = kind
|
||||
);
|
||||
|
||||
// TODO: can someone extract this to a function?
|
||||
macro_rules! call {
|
||||
($h:expr, $value:expr) => {{
|
||||
let value = $value;
|
||||
let handler = $h.iter().find_map(|e| {
|
||||
let (filter, handler) = e;
|
||||
if filter.test(&value) {
|
||||
Some(handler)
|
||||
} else {
|
||||
None
|
||||
// TODO: can someone extract this to a function?
|
||||
macro_rules! call {
|
||||
($h:expr, $value:expr) => {{
|
||||
let value = $value;
|
||||
let handler = $h.iter().find_map(|e| {
|
||||
let (filter, handler) = e;
|
||||
if filter.test(&value) {
|
||||
Some(handler)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
match handler {
|
||||
Some(handler) => {
|
||||
if let Err(err) =
|
||||
handler.handle(value).await
|
||||
{
|
||||
self.error_policy
|
||||
.handle_error(err)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
log::warn!("Unhandled update: {:?}", value)
|
||||
}
|
||||
}
|
||||
});
|
||||
}};
|
||||
}
|
||||
|
||||
match handler {
|
||||
Some(handler) => {
|
||||
if let Err(err) = handler.handle(value).await {
|
||||
self.error_policy.handle_error(err).await;
|
||||
}
|
||||
},
|
||||
None => log::warn!("Unhandled update: {:?}", value)
|
||||
match kind {
|
||||
UpdateKind::Message(mes) => {
|
||||
call!(self.message_handlers, mes)
|
||||
}
|
||||
}};
|
||||
UpdateKind::EditedMessage(mes) => {
|
||||
call!(self.edited_message_handlers, mes)
|
||||
}
|
||||
UpdateKind::ChannelPost(post) => {
|
||||
call!(self.channel_post_handlers, post)
|
||||
}
|
||||
UpdateKind::EditedChannelPost(post) => {
|
||||
call!(self.edited_channel_post_handlers, post)
|
||||
}
|
||||
UpdateKind::InlineQuery(query) => {
|
||||
call!(self.inline_query_handlers, query)
|
||||
}
|
||||
UpdateKind::ChosenInlineResult(result) => {
|
||||
call!(self.chosen_inline_result_handlers, result)
|
||||
}
|
||||
UpdateKind::CallbackQuery(callback) => {
|
||||
call!(self.callback_query_handlers, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match kind {
|
||||
UpdateKind::Message(mes) => call!(self.message_handlers, mes),
|
||||
UpdateKind::EditedMessage(mes) => call!(self.edited_message_handlers, mes),
|
||||
UpdateKind::ChannelPost(post) => call!(self.channel_post_handlers, post),
|
||||
UpdateKind::EditedChannelPost(post) => call!(self.edited_channel_post_handlers, post),
|
||||
UpdateKind::InlineQuery(query) => call!(self.inline_query_handlers, query),
|
||||
UpdateKind::ChosenInlineResult(result) => call!(self.chosen_inline_result_handlers, result),
|
||||
UpdateKind::CallbackQuery(callback) => call!(self.callback_query_handlers, callback),
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
#[async_trait(? Send)]
|
||||
impl<'a, U, E> crate::dispatcher::Dispatcher<'a, U> for Dispatcher<'a, E>
|
||||
where
|
||||
E: std::fmt::Debug,
|
||||
|
@ -235,26 +269,35 @@ mod tests {
|
|||
use std::convert::Infallible;
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
use crate::{
|
||||
types::{
|
||||
Message, ChatKind, MessageKind, Sender, ForwardKind, MediaKind, Chat, User, Update, UpdateKind
|
||||
},
|
||||
dispatcher::{simple::{Dispatcher, error_policy::ErrorPolicy}, updater::StreamUpdater},
|
||||
};
|
||||
use futures::Stream;
|
||||
|
||||
use crate::{
|
||||
dispatcher::{
|
||||
simple::{error_policy::ErrorPolicy, Dispatcher},
|
||||
updater::StreamUpdater,
|
||||
},
|
||||
types::{
|
||||
Chat, ChatKind, ForwardKind, MediaKind, Message, MessageKind,
|
||||
Sender, Update, UpdateKind, User,
|
||||
},
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn first_handler_executes_1_time() {
|
||||
let counter = &AtomicI32::new(0);
|
||||
let counter2 = &AtomicI32::new(0);
|
||||
|
||||
let mut dp = Dispatcher::<Infallible>::new(ErrorPolicy::Ignore)
|
||||
.message_handler(true, |_mes: Message| async move {
|
||||
counter.fetch_add(1, Ordering::SeqCst);
|
||||
.message_handler(true, |_mes: Message| {
|
||||
async move {
|
||||
counter.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
})
|
||||
.message_handler(true, |_mes: Message| async move {
|
||||
counter2.fetch_add(1, Ordering::SeqCst);
|
||||
Ok::<_, Infallible>(())
|
||||
.message_handler(true, |_mes: Message| {
|
||||
async move {
|
||||
counter2.fetch_add(1, Ordering::SeqCst);
|
||||
Ok::<_, Infallible>(())
|
||||
}
|
||||
});
|
||||
|
||||
dp.dispatch(one_message_updater()).await;
|
||||
|
@ -300,15 +343,17 @@ mod tests {
|
|||
}
|
||||
|
||||
fn message_update() -> Update {
|
||||
Update { id: 0, kind: UpdateKind::Message(message()) }
|
||||
Update {
|
||||
id: 0,
|
||||
kind: UpdateKind::Message(message()),
|
||||
}
|
||||
}
|
||||
|
||||
fn one_message_updater() -> StreamUpdater<impl Stream<Item=Result<Update, Infallible>>> {
|
||||
fn one_message_updater(
|
||||
) -> StreamUpdater<impl Stream<Item = Result<Update, Infallible>>> {
|
||||
use futures::future::ready;
|
||||
use futures::stream;
|
||||
|
||||
StreamUpdater::new(
|
||||
stream::once(ready(Ok(message_update())))
|
||||
)
|
||||
StreamUpdater::new(stream::once(ready(Ok(message_update()))))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,19 +3,18 @@ use std::{
|
|||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use pin_project::pin_project;
|
||||
use futures::{Stream, StreamExt, stream};
|
||||
use futures::{stream, Stream, StreamExt};
|
||||
|
||||
use pin_project::pin_project;
|
||||
|
||||
use crate::{
|
||||
types::Update,
|
||||
RequestError,
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
use crate::{types::Update, RequestError};
|
||||
|
||||
// Currently just a placeholder, but I'll add here some methods
|
||||
/// Updater is stream of updates.
|
||||
///
|
||||
/// Telegram supports 2 ways of [getting updates]: [long polling](Long Polling) and webhook
|
||||
/// Telegram supports 2 ways of [getting updates]: [long polling](Long Polling)
|
||||
/// and webhook
|
||||
///
|
||||
/// ## Long Polling
|
||||
///
|
||||
|
@ -99,14 +98,16 @@ use crate::bot::Bot;
|
|||
/// [GetUpdates]: crate::requests::GetUpdates
|
||||
/// [getting updates]: https://core.telegram.org/bots/api#getting-updates
|
||||
/// [wiki]: https://en.wikipedia.org/wiki/Push_technology#Long_polling
|
||||
pub trait Updater: Stream<Item=Result<Update, <Self as Updater>::Error>> {
|
||||
pub trait Updater:
|
||||
Stream<Item = Result<Update, <Self as Updater>::Error>>
|
||||
{
|
||||
type Error;
|
||||
}
|
||||
|
||||
#[pin_project]
|
||||
pub struct StreamUpdater<S> {
|
||||
#[pin]
|
||||
stream: S
|
||||
stream: S,
|
||||
}
|
||||
|
||||
impl<S> StreamUpdater<S> {
|
||||
|
@ -115,37 +116,49 @@ impl<S> StreamUpdater<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S, E> Stream for StreamUpdater<S> where S: Stream<Item=Result<Update, E>> {
|
||||
impl<S, E> Stream for StreamUpdater<S>
|
||||
where
|
||||
S: Stream<Item = Result<Update, E>>,
|
||||
{
|
||||
type Item = Result<Update, E>;
|
||||
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
fn poll_next(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<Option<Self::Item>> {
|
||||
self.project().stream.poll_next(cx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, E> Updater for StreamUpdater<S> where S: Stream<Item=Result<Update, E>> {
|
||||
impl<S, E> Updater for StreamUpdater<S>
|
||||
where
|
||||
S: Stream<Item = Result<Update, E>>,
|
||||
{
|
||||
type Error = E;
|
||||
}
|
||||
|
||||
pub fn polling<'a>(bot: &'a Bot) -> impl Updater<Error = RequestError> + 'a {
|
||||
let stream = stream::unfold((bot, 0), |(bot, mut offset)| async move {
|
||||
// this match converts Result<Vec<_>, _> -> Vec<Result<_, _>>
|
||||
let updates = match bot.get_updates().offset(offset).send().await {
|
||||
Ok(updates) => {
|
||||
if let Some(upd) = updates.last() {
|
||||
offset = upd.id + 1;
|
||||
let stream = stream::unfold((bot, 0), |(bot, mut offset)| {
|
||||
async move {
|
||||
// this match converts Result<Vec<_>, _> -> Vec<Result<_, _>>
|
||||
let updates = match bot.get_updates().offset(offset).send().await {
|
||||
Ok(updates) => {
|
||||
if let Some(upd) = updates.last() {
|
||||
offset = upd.id + 1;
|
||||
}
|
||||
updates.into_iter().map(|u| Ok(u)).collect::<Vec<_>>()
|
||||
}
|
||||
updates.into_iter().map(|u| Ok(u)).collect::<Vec<_>>()
|
||||
},
|
||||
Err(err) => vec![Err(err)]
|
||||
};
|
||||
Some((stream::iter(updates), (bot, offset)))
|
||||
Err(err) => vec![Err(err)],
|
||||
};
|
||||
Some((stream::iter(updates), (bot, offset)))
|
||||
}
|
||||
})
|
||||
.flatten();
|
||||
.flatten();
|
||||
|
||||
StreamUpdater { stream }
|
||||
}
|
||||
|
||||
// TODO implement webhook (this actually require webserver and probably we
|
||||
// should add cargo feature that adds webhook)
|
||||
//pub fn webhook<'a>(bot: &'a cfg: WebhookConfig) -> Updater<impl Stream<Item=Result<Update, ???>> + 'a> {}
|
||||
//pub fn webhook<'a>(bot: &'a cfg: WebhookConfig) -> Updater<impl
|
||||
// Stream<Item=Result<Update, ???>> + 'a> {}
|
||||
|
|
|
@ -11,8 +11,8 @@ pub async fn request_multipart<T>(
|
|||
method_name: &str,
|
||||
params: Form,
|
||||
) -> ResponseResult<T>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
process_response(
|
||||
client
|
||||
|
@ -30,8 +30,8 @@ pub async fn request_simple<T>(
|
|||
token: &str,
|
||||
method_name: &str,
|
||||
) -> ResponseResult<T>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
process_response(
|
||||
client
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
types::True,
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
/// Once the user has confirmed their payment and shipping details, the Bot API
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ShippingOption, True},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
/// If you sent an invoice requesting a shipping address and the parameter
|
||||
|
@ -60,11 +60,7 @@ impl AnswerShippingQuery<'_> {
|
|||
}
|
||||
|
||||
impl<'a> AnswerShippingQuery<'a> {
|
||||
pub(crate) fn new<S, B>(
|
||||
bot: &'a Bot,
|
||||
shipping_query_id: S,
|
||||
ok: B,
|
||||
) -> Self
|
||||
pub(crate) fn new<S, B>(bot: &'a Bot, shipping_query_id: S, ok: B) -> Self
|
||||
where
|
||||
S: Into<String>,
|
||||
B: Into<bool>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
/// Use this method to edit live location messages. A location can be edited
|
||||
|
@ -64,11 +64,7 @@ impl EditMessageLiveLocation<'_> {
|
|||
}
|
||||
|
||||
impl<'a> EditMessageLiveLocation<'a> {
|
||||
pub(crate) fn new<Lt, Lg>(
|
||||
bot: &'a Bot,
|
||||
latitude: Lt,
|
||||
longitude: Lg,
|
||||
) -> Self
|
||||
pub(crate) fn new<Lt, Lg>(bot: &'a Bot, latitude: Lt, longitude: Lg) -> Self
|
||||
where
|
||||
Lt: Into<f64>,
|
||||
Lg: Into<f64>,
|
||||
|
|
|
@ -2,11 +2,11 @@ use std::path::PathBuf;
|
|||
|
||||
use reqwest::multipart::Form;
|
||||
|
||||
use crate::types::InputFile;
|
||||
use crate::{
|
||||
requests::utils,
|
||||
types::{ChatId, InputMedia, ParseMode},
|
||||
};
|
||||
use crate::types::InputFile;
|
||||
|
||||
/// This is a convenient struct that builds `reqwest::multipart::Form`
|
||||
/// from scratch.
|
||||
|
@ -73,7 +73,10 @@ macro_rules! impl_for_struct {
|
|||
|
||||
impl_for_struct!(bool, i32, i64);
|
||||
|
||||
impl<T> IntoFormValue for Option<T> where T: IntoFormValue {
|
||||
impl<T> IntoFormValue for Option<T>
|
||||
where
|
||||
T: IntoFormValue,
|
||||
{
|
||||
fn into_form_value(self) -> Option<FormValue> {
|
||||
self.and_then(IntoFormValue::into_form_value)
|
||||
}
|
||||
|
@ -81,8 +84,8 @@ impl<T> IntoFormValue for Option<T> where T: IntoFormValue {
|
|||
|
||||
impl IntoFormValue for &[InputMedia] {
|
||||
fn into_form_value(self) -> Option<FormValue> {
|
||||
let json = serde_json::to_string(self)
|
||||
.expect("serde_json::to_string failed");
|
||||
let json =
|
||||
serde_json::to_string(self).expect("serde_json::to_string failed");
|
||||
Some(FormValue::Str(json))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
/// Use this method to forward messages of any kind. On success, the sent
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{Chat, ChatId},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to get up to date information about the chat
|
||||
/// (current name of the user for one-on-one conversations,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::File,
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to get basic info about a file and prepare it for
|
||||
/// downloading. For the moment, bots can download files of up to 20MB in size.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::User,
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// A simple method for testing your bot's auth token. Requires no parameters.
|
||||
|
@ -25,7 +25,8 @@ impl Request for GetMe<'_> {
|
|||
|
||||
impl GetMe<'_> {
|
||||
pub async fn send(self) -> ResponseResult<User> {
|
||||
network::request_simple(self.bot.client(), self.bot.token(), "getMe").await
|
||||
network::request_simple(self.bot.client(), self.bot.token(), "getMe")
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::Update,
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct GetUpdates<'a> {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::UserProfilePhotos,
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
///Use this method to get a list of profile pictures for a user. Returns a
|
||||
/// UserProfilePhotos object.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, True},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to kick a user from a group, a supergroup or a channel. In
|
||||
/// the case of supergroups and channels, the user will not be able to return to
|
||||
|
@ -50,11 +50,7 @@ impl KickChatMember<'_> {
|
|||
}
|
||||
|
||||
impl<'a> KickChatMember<'a> {
|
||||
pub(crate) fn new<C, U>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
user_id: U,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, U>(bot: &'a Bot, chat_id: C, user_id: U) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
U: Into<i32>,
|
||||
|
|
|
@ -71,4 +71,4 @@ pub trait Request {
|
|||
|
||||
/// Send this request.
|
||||
async fn send_boxed(self) -> ResponseResult<Self::Output>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, True},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to get up to date information about the chat
|
||||
/// (current name of the user for one-on-one conversations,
|
||||
|
@ -23,11 +23,7 @@ pub struct PinChatMessage<'a> {
|
|||
}
|
||||
|
||||
impl<'a> PinChatMessage<'a> {
|
||||
pub(crate) fn new<C, M>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
message_id: M,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, M>(bot: &'a Bot, chat_id: C, message_id: M) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
M: Into<i32>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, True},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
///Use this method to promote or demote a user in a supergroup or a channel.
|
||||
/// The bot must be an administrator in the chat for this to work and must have
|
||||
|
@ -73,11 +73,7 @@ impl PromoteChatMember<'_> {
|
|||
}
|
||||
|
||||
impl<'a> PromoteChatMember<'a> {
|
||||
pub(crate) fn new<C, U>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
user_id: U,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, U>(bot: &'a Bot, chat_id: C, user_id: U) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
U: Into<i32>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, ChatPermissions, True},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to restrict a user in a supergroup. The bot must be an
|
||||
/// administrator in the supergroup for this to work and must have the
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::network;
|
||||
use crate::requests::{Request, ResponseResult};
|
||||
use crate::types::{ChatId, Message, ParseMode, ReplyMarkup};
|
||||
use crate::bot::Bot;
|
||||
use crate::network;
|
||||
use crate::requests::{Request, ResponseResult};
|
||||
use crate::types::{ChatId, Message, ParseMode, ReplyMarkup};
|
||||
|
||||
///TODO: add to bot api
|
||||
///Use this method to send animation files (GIF or H.264/MPEG-4 AVC video
|
||||
|
@ -87,11 +87,7 @@ impl SendAnimation<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendAnimation<'a> {
|
||||
pub(crate) fn new<C, S>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
animation: S,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, S>(bot: &'a Bot, chat_id: C, animation: S) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
S: Into<String>,
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{
|
||||
form_builder::FormBuilder, Request, ResponseResult,
|
||||
},
|
||||
requests::{form_builder::FormBuilder, Request, ResponseResult},
|
||||
types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to send audio files, if you want Telegram clients to display
|
||||
/// them in the music player. Your audio must be in the .mp3 format. On success,
|
||||
|
@ -87,7 +85,6 @@ impl SendAudio<'_> {
|
|||
.add("audio", self.audio)
|
||||
.add("thumb", self.thumb);
|
||||
|
||||
|
||||
network::request_multipart(
|
||||
self.bot.client(),
|
||||
self.bot.token(),
|
||||
|
@ -99,11 +96,7 @@ impl SendAudio<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendAudio<'a> {
|
||||
pub(crate) fn new<C, A>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
audio: A,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, A>(bot: &'a Bot, chat_id: C, audio: A) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
A: Into<InputFile>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatAction, ChatId, True},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
///Use this method when you need to tell the user that something is happening
|
||||
/// on the bot's side. The status is set for 5 seconds or less (when a message
|
||||
|
@ -48,7 +48,7 @@ impl SendChatAction<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendChatAction<'a> {
|
||||
pub(crate) fn new<Cid, Ca>(bot: &'a Bot, chat_id: Cid, action: Ca,) -> Self
|
||||
pub(crate) fn new<Cid, Ca>(bot: &'a Bot, chat_id: Cid, action: Ca) -> Self
|
||||
where
|
||||
Cid: Into<ChatId>,
|
||||
Ca: Into<ChatAction>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to send phone contacts.
|
||||
/// returned.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ParseMode, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
// TODO: add method to bot/api
|
||||
|
||||
|
@ -80,11 +80,7 @@ impl SendDocument<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendDocument<'a> {
|
||||
pub(crate) fn new<C, D>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
document: D,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, D>(bot: &'a Bot, chat_id: C, document: D) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
D: Into<String>,
|
||||
|
|
|
@ -2,12 +2,12 @@ use serde::Serialize;
|
|||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
/// Use this method to send point on the map. On success, the sent [`Message`]
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network::request_multipart,
|
||||
requests::{
|
||||
form_builder::FormBuilder, Request, ResponseResult,
|
||||
},
|
||||
types::{ChatId, InputMedia, Message, InputFile},
|
||||
requests::{form_builder::FormBuilder, Request, ResponseResult},
|
||||
types::{ChatId, InputFile, InputMedia, Message},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to send a group of photos or videos as an album.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -38,13 +36,16 @@ impl SendMediaGroup<'_> {
|
|||
.add("disable_notification", self.disable_notification)
|
||||
.add("reply_to_message_id", self.reply_to_message_id);
|
||||
|
||||
let form = self.media.into_iter().filter_map(|e| InputFile::from(e).into())
|
||||
.fold(form, |acc, path: std::path::PathBuf|
|
||||
acc.add_file(
|
||||
&path.file_name().unwrap().to_string_lossy().into_owned(),
|
||||
path,
|
||||
)
|
||||
);
|
||||
let form = self
|
||||
.media
|
||||
.into_iter()
|
||||
.filter_map(|e| InputFile::from(e).into())
|
||||
.fold(form, |acc, path: std::path::PathBuf| {
|
||||
acc.add_file(
|
||||
&path.file_name().unwrap().to_string_lossy().into_owned(),
|
||||
path,
|
||||
)
|
||||
});
|
||||
|
||||
request_multipart(
|
||||
self.bot.client(),
|
||||
|
@ -57,11 +58,7 @@ impl SendMediaGroup<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendMediaGroup<'a> {
|
||||
pub(crate) fn new<C, M>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
media: M,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, M>(bot: &'a Bot, chat_id: C, media: M) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
M: Into<Vec<InputMedia>>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ParseMode, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
/// Use this method to send text messages. On success, the sent [`Message`] is
|
||||
|
@ -66,7 +66,7 @@ impl SendMessage<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendMessage<'a> {
|
||||
pub(crate) fn new<C, S>(bot: &'a Bot, chat_id: C, text: S,) -> Self
|
||||
pub(crate) fn new<C, S>(bot: &'a Bot, chat_id: C, text: S) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
S: Into<String>,
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{
|
||||
form_builder::FormBuilder, Request, ResponseResult,
|
||||
},
|
||||
requests::{form_builder::FormBuilder, Request, ResponseResult},
|
||||
types::{ChatId, InputFile, Message, ParseMode, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// Use this method to send photos. On success, the sent [`Message`] is
|
||||
|
@ -75,11 +73,7 @@ impl SendPhoto<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendPhoto<'a> {
|
||||
pub(crate) fn new<C, P>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
photo: P,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, P>(bot: &'a Bot, chat_id: C, photo: P) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
P: Into<InputFile>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to send a native poll. A native poll can't be sent to a
|
||||
/// private chat. On success, the sent Message is returned.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to send information about a venue.
|
||||
/// Message is returned.
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::network;
|
||||
use crate::requests::{Request, ResponseResult};
|
||||
use crate::types::{ChatId, Message, ParseMode, ReplyMarkup};
|
||||
use crate::bot::Bot;
|
||||
use crate::network;
|
||||
use crate::requests::{Request, ResponseResult};
|
||||
use crate::types::{ChatId, Message, ParseMode, ReplyMarkup};
|
||||
|
||||
//TODO: add action to bot api
|
||||
///Use this method to send video files, Telegram clients support mp4 videos
|
||||
|
@ -89,11 +89,7 @@ impl SendVideo<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendVideo<'a> {
|
||||
pub(crate) fn new<C, V>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
video: V,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, V>(bot: &'a Bot, chat_id: C, video: V) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
V: Into<String>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
///As of v.4.0, Telegram clients support rounded square mp4 videos of up to 1
|
||||
/// minute long. Use this method to send video messages. On success, the sent
|
||||
|
@ -76,11 +76,7 @@ impl SendVideoNote<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendVideoNote<'a> {
|
||||
pub(crate) fn new<C, V>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
video_note: V,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, V>(bot: &'a Bot, chat_id: C, video_note: V) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
V: Into<String>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, Message, ParseMode, ReplyMarkup},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
///Use this method to send audio files, if you want Telegram clients to display
|
||||
/// the file as a playable voice message. For this to work, your audio must be
|
||||
|
@ -73,11 +73,7 @@ impl SendVoice<'_> {
|
|||
}
|
||||
|
||||
impl<'a> SendVoice<'a> {
|
||||
pub(crate) fn new<C, V>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
voice: V,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, V>(bot: &'a Bot, chat_id: C, voice: V) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
V: Into<String>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, InlineKeyboardMarkup, Message},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to stop updating a live location message before live_period
|
||||
/// expires. On success, if the message was sent by the bot, the sent Message is
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::ChatId,
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
/// Use this method to unban a previously kicked user in a supergroup or
|
||||
/// channel. The user will not return to the group or channel automatically, but
|
||||
|
@ -44,11 +44,7 @@ impl UnbanChatMember<'_> {
|
|||
}
|
||||
|
||||
impl<'a> UnbanChatMember<'a> {
|
||||
pub(crate) fn new<C, U>(
|
||||
bot: &'a Bot,
|
||||
chat_id: C,
|
||||
user_id: U,
|
||||
) -> Self
|
||||
pub(crate) fn new<C, U>(bot: &'a Bot, chat_id: C, user_id: U) -> Self
|
||||
where
|
||||
C: Into<ChatId>,
|
||||
U: Into<i32>,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use crate::bot::Bot;
|
||||
use crate::{
|
||||
network,
|
||||
requests::{Request, ResponseResult},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{ChatId, True},
|
||||
};
|
||||
use crate::bot::Bot;
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct UnpinChatMessage<'a> {
|
||||
|
|
|
@ -16,9 +16,7 @@ pub struct InlineKeyboardMarkup {
|
|||
///
|
||||
/// Example:
|
||||
/// ```
|
||||
/// use telebofr::types::{
|
||||
/// InlineKeyboardButton, InlineKeyboardMarkup,
|
||||
/// };
|
||||
/// use telebofr::types::{InlineKeyboardButton, InlineKeyboardMarkup};
|
||||
///
|
||||
/// let url_button = InlineKeyboardButton::url(
|
||||
/// "text".to_string(),
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
use crate::types::{Animation, Audio, Chat, Contact, Document, Game, InlineKeyboardMarkup, Invoice, Location, MessageEntity, PassportData, PhotoSize, Poll, Sticker, SuccessfulPayment, User, Venue, Video, VideoNote, Voice, True};
|
||||
use crate::types::{
|
||||
Animation, Audio, Chat, Contact, Document, Game, InlineKeyboardMarkup,
|
||||
Invoice, Location, MessageEntity, PassportData, PhotoSize, Poll, Sticker,
|
||||
SuccessfulPayment, True, User, Venue, Video, VideoNote, Voice,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Clone)]
|
||||
pub struct Message {
|
||||
|
@ -10,7 +14,6 @@ pub struct Message {
|
|||
pub kind: MessageKind,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Deserialize, PartialEq, Clone)]
|
||||
#[serde(untagged)]
|
||||
pub enum MessageKind {
|
||||
|
@ -187,24 +190,25 @@ pub enum MediaKind {
|
|||
mod getters {
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::types::message::MessageKind::{Pinned, SupergroupChatCreated};
|
||||
use crate::types::{
|
||||
self, Message, Sender, User, ForwardedFrom, Chat, MessageEntity,
|
||||
PhotoSize, True,
|
||||
self,
|
||||
message::{
|
||||
MessageKind::{
|
||||
Common, NewChatMembers, LeftChatMember, NewChatTitle,
|
||||
NewChatPhoto, DeleteChatPhoto, GroupChatCreated,
|
||||
ChannelChatCreated, Migrate, Invoice, SuccessfulPayment,
|
||||
ConnectedWebsite, PassportData
|
||||
},
|
||||
ForwardKind::{ChannelForward, NonChannelForward, Origin},
|
||||
MediaKind::{
|
||||
Text, Video, Photo, Animation, Audio, Document, Voice, Game,
|
||||
Sticker, VideoNote, Contact, Location, Poll, Venue
|
||||
Animation, Audio, Contact, Document, Game, Location, Photo,
|
||||
Poll, Sticker, Text, Venue, Video, VideoNote, Voice,
|
||||
},
|
||||
MessageKind::{
|
||||
ChannelChatCreated, Common, ConnectedWebsite, DeleteChatPhoto,
|
||||
GroupChatCreated, Invoice, LeftChatMember, Migrate,
|
||||
NewChatMembers, NewChatPhoto, NewChatTitle, PassportData,
|
||||
SuccessfulPayment,
|
||||
},
|
||||
ForwardKind::{NonChannelForward, ChannelForward, Origin}
|
||||
},
|
||||
Chat, ForwardedFrom, Message, MessageEntity, PhotoSize, Sender, True,
|
||||
User,
|
||||
};
|
||||
use crate::types::message::MessageKind::{SupergroupChatCreated, Pinned};
|
||||
|
||||
/// Getters for [Message] fields from [telegram docs].
|
||||
///
|
||||
|
@ -223,49 +227,67 @@ mod getters {
|
|||
/// `forward_sender_name`
|
||||
pub fn forward_from(&self) -> Option<&ForwardedFrom> {
|
||||
match &self.kind {
|
||||
Common { forward_kind: NonChannelForward { from, .. }, .. } =>
|
||||
Some(from),
|
||||
Common {
|
||||
forward_kind: NonChannelForward { from, .. },
|
||||
..
|
||||
} => Some(from),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn forward_from_chat(&self) -> Option<&Chat> {
|
||||
match &self.kind {
|
||||
Common { forward_kind: ChannelForward { chat, .. }, .. } =>
|
||||
Some(chat),
|
||||
Common {
|
||||
forward_kind: ChannelForward { chat, .. },
|
||||
..
|
||||
} => Some(chat),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn forward_from_message_id(&self) -> Option<&i32> {
|
||||
match &self.kind {
|
||||
Common { forward_kind: ChannelForward { message_id, .. }, .. } =>
|
||||
Some(message_id),
|
||||
Common {
|
||||
forward_kind: ChannelForward { message_id, .. },
|
||||
..
|
||||
} => Some(message_id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn forward_signature(&self) -> Option<&str> {
|
||||
match &self.kind {
|
||||
Common { forward_kind: ChannelForward { signature, .. }, .. } =>
|
||||
signature.as_ref().map(Deref::deref),
|
||||
Common {
|
||||
forward_kind: ChannelForward { signature, .. },
|
||||
..
|
||||
} => signature.as_ref().map(Deref::deref),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn forward_date(&self) -> Option<&i32> {
|
||||
match &self.kind {
|
||||
Common { forward_kind: ChannelForward { date, .. }, .. } |
|
||||
Common { forward_kind: NonChannelForward { date, .. }, .. } =>
|
||||
Some(date),
|
||||
Common {
|
||||
forward_kind: ChannelForward { date, .. },
|
||||
..
|
||||
}
|
||||
| Common {
|
||||
forward_kind: NonChannelForward { date, .. },
|
||||
..
|
||||
} => Some(date),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reply_to_message(&self) -> Option<&Message> {
|
||||
match &self.kind {
|
||||
Common { forward_kind: Origin { reply_to_message, .. }, .. } =>
|
||||
reply_to_message.as_ref().map(Deref::deref),
|
||||
Common {
|
||||
forward_kind:
|
||||
Origin {
|
||||
reply_to_message, ..
|
||||
},
|
||||
..
|
||||
} => reply_to_message.as_ref().map(Deref::deref),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -279,104 +301,172 @@ mod getters {
|
|||
|
||||
pub fn media_group_id(&self) -> Option<&str> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Video { media_group_id, .. }, .. } |
|
||||
Common { media_kind: Photo { media_group_id, .. }, .. } =>
|
||||
media_group_id.as_ref().map(Deref::deref),
|
||||
Common {
|
||||
media_kind: Video { media_group_id, .. },
|
||||
..
|
||||
}
|
||||
| Common {
|
||||
media_kind: Photo { media_group_id, .. },
|
||||
..
|
||||
} => media_group_id.as_ref().map(Deref::deref),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text(&self) -> Option<&str> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Text { text, .. }, .. } => Some(text),
|
||||
Common {
|
||||
media_kind: Text { text, .. },
|
||||
..
|
||||
} => Some(text),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn entities(&self) -> Option<&[MessageEntity]> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Text { entities, .. }, .. } =>
|
||||
Some(entities),
|
||||
Common {
|
||||
media_kind: Text { entities, .. },
|
||||
..
|
||||
} => Some(entities),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn caption_entities(&self) -> Option<&[MessageEntity]> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Animation { caption_entities, .. }, .. } |
|
||||
Common { media_kind: Audio { caption_entities, .. }, .. } |
|
||||
Common { media_kind: Document { caption_entities, .. }, .. } |
|
||||
Common { media_kind: Photo { caption_entities, .. }, .. } |
|
||||
Common { media_kind: Video { caption_entities, .. }, .. } |
|
||||
Common { media_kind: Voice { caption_entities, .. }, .. } =>
|
||||
Some(caption_entities),
|
||||
Common {
|
||||
media_kind:
|
||||
Animation {
|
||||
caption_entities, ..
|
||||
},
|
||||
..
|
||||
}
|
||||
| Common {
|
||||
media_kind:
|
||||
Audio {
|
||||
caption_entities, ..
|
||||
},
|
||||
..
|
||||
}
|
||||
| Common {
|
||||
media_kind:
|
||||
Document {
|
||||
caption_entities, ..
|
||||
},
|
||||
..
|
||||
}
|
||||
| Common {
|
||||
media_kind:
|
||||
Photo {
|
||||
caption_entities, ..
|
||||
},
|
||||
..
|
||||
}
|
||||
| Common {
|
||||
media_kind:
|
||||
Video {
|
||||
caption_entities, ..
|
||||
},
|
||||
..
|
||||
}
|
||||
| Common {
|
||||
media_kind:
|
||||
Voice {
|
||||
caption_entities, ..
|
||||
},
|
||||
..
|
||||
} => Some(caption_entities),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn audio(&self) -> Option<&types::Audio> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Audio { audio, .. }, .. } => Some(audio),
|
||||
Common {
|
||||
media_kind: Audio { audio, .. },
|
||||
..
|
||||
} => Some(audio),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn document(&self) -> Option<&types::Document> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Document { document, .. }, .. } =>
|
||||
Some(document),
|
||||
Common {
|
||||
media_kind: Document { document, .. },
|
||||
..
|
||||
} => Some(document),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn animation(&self) -> Option<&types::Animation> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Animation { animation, .. }, .. } =>
|
||||
Some(animation),
|
||||
Common {
|
||||
media_kind: Animation { animation, .. },
|
||||
..
|
||||
} => Some(animation),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn game(&self) -> Option<&types::Game> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Game { game, .. }, .. } => Some(game),
|
||||
Common {
|
||||
media_kind: Game { game, .. },
|
||||
..
|
||||
} => Some(game),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn photo(&self) -> Option<&[PhotoSize]> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Photo { photo, .. }, .. } => Some(photo),
|
||||
Common {
|
||||
media_kind: Photo { photo, .. },
|
||||
..
|
||||
} => Some(photo),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sticker(&self) -> Option<&types::Sticker> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Sticker { sticker, .. }, .. } =>
|
||||
Some(sticker),
|
||||
Common {
|
||||
media_kind: Sticker { sticker, .. },
|
||||
..
|
||||
} => Some(sticker),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn video(&self) -> Option<&types::Video> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Video { video, .. }, .. } => Some(video),
|
||||
Common {
|
||||
media_kind: Video { video, .. },
|
||||
..
|
||||
} => Some(video),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn voice(&self) -> Option<&types::Voice> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Voice { voice, .. }, .. } => Some(voice),
|
||||
Common {
|
||||
media_kind: Voice { voice, .. },
|
||||
..
|
||||
} => Some(voice),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn video_note(&self) -> Option<&types::VideoNote> {
|
||||
match &self.kind {
|
||||
Common { media_kind: VideoNote { video_note, .. }, .. } =>
|
||||
Some(video_note),
|
||||
Common {
|
||||
media_kind: VideoNote { video_note, .. },
|
||||
..
|
||||
} => Some(video_note),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -384,12 +474,14 @@ mod getters {
|
|||
pub fn caption(&self) -> Option<&str> {
|
||||
match &self.kind {
|
||||
Common { media_kind, .. } => match media_kind {
|
||||
Animation { caption, ..} |
|
||||
Audio { caption, ..} |
|
||||
Document { caption, ..} |
|
||||
Photo { caption, ..} |
|
||||
Video { caption, ..} |
|
||||
Voice { caption, ..} => caption.as_ref().map(Deref::deref),
|
||||
Animation { caption, .. }
|
||||
| Audio { caption, .. }
|
||||
| Document { caption, .. }
|
||||
| Photo { caption, .. }
|
||||
| Video { caption, .. }
|
||||
| Voice { caption, .. } => {
|
||||
caption.as_ref().map(Deref::deref)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
@ -398,29 +490,40 @@ mod getters {
|
|||
|
||||
pub fn contact(&self) -> Option<&types::Contact> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Contact { contact }, .. } => Some(contact),
|
||||
Common {
|
||||
media_kind: Contact { contact },
|
||||
..
|
||||
} => Some(contact),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn location(&self) -> Option<&types::Location> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Location { location, .. }, .. } =>
|
||||
Some(location),
|
||||
Common {
|
||||
media_kind: Location { location, .. },
|
||||
..
|
||||
} => Some(location),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn venue(&self) -> Option<&types::Venue> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Venue { venue, .. }, .. } => Some(venue),
|
||||
Common {
|
||||
media_kind: Venue { venue, .. },
|
||||
..
|
||||
} => Some(venue),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll(&self) -> Option<&types::Poll> {
|
||||
match &self.kind {
|
||||
Common { media_kind: Poll { poll, .. }, .. } => Some(poll),
|
||||
Common {
|
||||
media_kind: Poll { poll, .. },
|
||||
..
|
||||
} => Some(poll),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -457,47 +560,55 @@ mod getters {
|
|||
// mb smt like `is_delete_chat_photo(&self) -> bool`?
|
||||
pub fn delete_chat_photo(&self) -> Option<True> {
|
||||
match &self.kind {
|
||||
DeleteChatPhoto { delete_chat_photo } =>
|
||||
Some(*delete_chat_photo),
|
||||
DeleteChatPhoto { delete_chat_photo } => {
|
||||
Some(*delete_chat_photo)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn group_chat_created(&self) -> Option<True> {
|
||||
match &self.kind {
|
||||
GroupChatCreated { group_chat_created } =>
|
||||
Some(*group_chat_created),
|
||||
GroupChatCreated { group_chat_created } => {
|
||||
Some(*group_chat_created)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn super_group_chat_created(&self) -> Option<True> {
|
||||
match &self.kind {
|
||||
SupergroupChatCreated { supergroup_chat_created } =>
|
||||
Some(*supergroup_chat_created),
|
||||
SupergroupChatCreated {
|
||||
supergroup_chat_created,
|
||||
} => Some(*supergroup_chat_created),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn channel_chat_created(&self) -> Option<True> {
|
||||
match &self.kind {
|
||||
ChannelChatCreated { channel_chat_created } =>
|
||||
Some(*channel_chat_created),
|
||||
ChannelChatCreated {
|
||||
channel_chat_created,
|
||||
} => Some(*channel_chat_created),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn migrate_to_chat_id(&self) -> Option<&i64> {
|
||||
match &self.kind {
|
||||
Migrate { migrate_to_chat_id, .. } => Some(migrate_to_chat_id),
|
||||
Migrate {
|
||||
migrate_to_chat_id, ..
|
||||
} => Some(migrate_to_chat_id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn migrate_from_chat_id(&self) -> Option<&i64> {
|
||||
match &self.kind {
|
||||
Migrate { migrate_from_chat_id, .. } =>
|
||||
Some(migrate_from_chat_id),
|
||||
Migrate {
|
||||
migrate_from_chat_id,
|
||||
..
|
||||
} => Some(migrate_from_chat_id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -516,25 +627,24 @@ mod getters {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn successful_payment(&self) -> Option<&types::SuccessfulPayment> {
|
||||
match &self.kind {
|
||||
SuccessfulPayment { successful_payment } =>
|
||||
Some(successful_payment),
|
||||
SuccessfulPayment { successful_payment } => {
|
||||
Some(successful_payment)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn connected_website(&self) -> Option<&str> {
|
||||
match &self.kind {
|
||||
ConnectedWebsite { connected_website } =>
|
||||
Some(connected_website),
|
||||
ConnectedWebsite { connected_website } => {
|
||||
Some(connected_website)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn passport_data(&self) -> Option<&types::PassportData> {
|
||||
match &self.kind {
|
||||
PassportData { passport_data } => Some(passport_data),
|
||||
|
@ -542,7 +652,6 @@ mod getters {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn reply_markup(&self) -> Option<&types::InlineKeyboardMarkup> {
|
||||
match &self.kind {
|
||||
Common { reply_markup, .. } => reply_markup.as_ref(),
|
||||
|
@ -552,7 +661,6 @@ mod getters {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::from_str;
|
||||
|
|
Loading…
Reference in a new issue