use crate::{
client::Reqwest,
enums::{
telegram_observer_type::with_telegram_observer_variants, TelegramObserverType, UpdateType,
},
errors::EventErrorKind,
event::{
bases::{EventReturn, PropagateEventResult},
service::Service as _,
simple::{HandlerResult as SimpleHandlerResult, Observer as SimpleObserver},
telegram::Observer as TelegramObserver,
},
middlewares::{
inner::{
boxed_middleware_factory as boxed_inner_middleware_factory,
BoxedCloneMiddlewareService as BoxedCloneInnerMiddlewareService,
Logging as LoggingMiddleware,
},
outer::{
boxed_middleware_factory as boxed_outer_middleware_factory,
BoxedCloneMiddlewareService as BoxedCloneOuterMiddlewareService,
UserContext as UserContextMiddleware,
},
InnerMiddleware, OuterMiddleware,
},
Request,
};
use paste::paste;
use std::{
collections::HashSet,
fmt::{self, Debug, Formatter},
future::Future,
iter::once,
};
use tracing::{event, instrument, Level};
pub struct Response<Client> {
pub request: Request<Client>,
pub propagate_result: PropagateEventResult<Client>,
}
impl<Client> Response<Client> {
#[inline]
#[must_use]
pub fn new(request: Request<Client>, propagate_result: PropagateEventResult<Client>) -> Self {
Self {
request,
propagate_result,
}
}
}
impl<Client> fmt::Debug for Response<Client> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Response")
.field("request", &self.request)
.field("propagate_result", &self.propagate_result)
.finish()
}
}
pub trait PropagateEvent<Client>: Clone + Send + Sync + 'static {
fn propagate_event(
&mut self,
update_type: UpdateType,
request: Request<Client>,
) -> impl Future<Output = Result<Response<Client>, EventErrorKind>> + Send
where
Client: Send + Sync + Clone;
fn propagate_update_event(
&mut self,
request: Request<Client>,
) -> impl Future<Output = Result<Response<Client>, EventErrorKind>> + Send
where
Client: Send + Sync + Clone;
fn emit_startup(&mut self) -> impl Future<Output = SimpleHandlerResult> + Send;
fn startup_handlers_len(&self) -> usize;
fn emit_shutdown(&mut self) -> impl Future<Output = SimpleHandlerResult> + Send;
fn shutdown_handlers_len(&self) -> usize;
}
macro_rules! define_router_struct {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
pub struct Router<Client = Reqwest> {
name: &'static str,
sub_routers: Vec<Router<Client>>,
$(
$observer: TelegramObserver<Client>,
)+
startup: SimpleObserver,
shutdown: SimpleObserver,
}
};
}
with_telegram_observer_variants!(define_router_struct);
macro_rules! router_constructor {
($name:expr, $(($variant:ident, $observer:ident)),+ $(,)?) => {
Self {
name: $name,
sub_routers: vec![],
$(
$observer: TelegramObserver::new(stringify!($observer)),
)+
startup: SimpleObserver::new("startup"),
shutdown: SimpleObserver::new("shutdown"),
}
};
}
macro_rules! impl_router_on_methods {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
$(
paste! {
#[doc = concat!("Configure `", stringify!($observer), "` observer in builder style")]
#[must_use]
pub fn [<on_ $observer>]<F>(mut self, configure: F) -> Self
where
F: FnOnce(TelegramObserver<Client>) -> TelegramObserver<Client>,
{
self.$observer = configure(self.$observer);
self
}
}
)+
#[must_use]
pub fn on_all<F>(mut self, mut configure: F) -> Self
where
F: FnMut(TelegramObserver<Client>) -> TelegramObserver<Client>,
{
$(
self.$observer = configure(self.$observer);
)+
self
}
#[must_use]
pub fn on_startup<F>(mut self, configure: F) -> Self
where
F: FnOnce(SimpleObserver) -> SimpleObserver,
{
self.startup = configure(self.startup);
self
}
#[must_use]
pub fn on_shutdown<F>(mut self, configure: F) -> Self
where
F: FnOnce(SimpleObserver) -> SimpleObserver,
{
self.shutdown = configure(self.shutdown);
self
}
};
}
macro_rules! observer_refs_array {
(ref, $ty:ident, $(($variant:ident, $observer:ident)),+ $(,)?) => {
[
$(
&$ty.$observer,
)+
]
};
(mut, $ty:ident, $(($variant:ident, $observer:ident)),+ $(,)?) => {
[
$(
&mut $ty.$observer,
)+
]
};
}
impl<Client> Router<Client>
where
Client: Send + Sync + 'static,
{
with_telegram_observer_variants!(impl_router_on_methods);
#[must_use]
#[rustfmt::skip]
pub fn new(name: &'static str) -> Self {
with_telegram_observer_variants!(router_constructor, name)
}
#[must_use]
pub fn include_router(mut self, router: impl Into<Router<Client>>) -> Self {
self.sub_routers.push(router.into());
self
}
#[inline]
#[must_use]
pub fn include(self, router: impl Into<Router<Client>>) -> Self {
self.include_router(router)
}
}
impl<Client> Router<Client> {
#[must_use]
const fn telegram_observers(&self) -> [&TelegramObserver<Client>; 25] {
with_telegram_observer_variants!(observer_refs_array, ref, self)
}
#[inline]
#[must_use]
#[cfg(test)]
const fn event_observers(&self) -> [&SimpleObserver; 2] {
[&self.startup, &self.shutdown]
}
#[must_use]
pub fn resolve_used_update_types_with_skip(
&self,
skip_update_types: impl IntoIterator<Item = &'static str>,
) -> HashSet<&'static str> {
let skip_update_types = skip_update_types.into_iter().collect::<HashSet<_>>();
let mut used_update_types = HashSet::new();
for observer in self.telegram_observers() {
if observer.handlers.is_empty() {
continue;
}
if skip_update_types.contains(observer.event_name) {
continue;
}
used_update_types.insert(observer.event_name);
}
for router in &self.sub_routers {
used_update_types
.extend(router.resolve_used_update_types_with_skip(skip_update_types.clone()));
}
used_update_types
}
#[inline]
#[must_use]
pub fn resolve_used_update_types(&self) -> HashSet<&'static str> {
self.resolve_used_update_types_with_skip([])
}
}
impl<Client> Router<Client> {
#[must_use]
#[allow(clippy::too_many_lines)]
pub fn configure(mut self, mut config: Config<Client>) -> Configured<Client> {
macro_rules! register_inner_middlewares_to_sub_routers {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
$(
for sub_router in self.sub_routers.iter_mut() {
for (index, middleware) in self.$observer.inner_middlewares.middlewares.clone().into_iter().enumerate() {
sub_router.$observer.inner_middlewares.register_boxed_at_position(index, middleware);
}
}
)+
};
}
with_telegram_observer_variants!(register_inner_middlewares_to_sub_routers);
macro_rules! register_middlewares_from_config {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
$(
for (index, middleware) in config.outer_middlewares.$observer.iter().enumerate() {
self.$observer.outer_middlewares.register_boxed_at_position(index, middleware.clone());
}
for (index, middleware) in config.inner_middlewares.$observer.iter().enumerate() {
self.$observer.inner_middlewares.register_boxed_at_position(index, middleware.clone());
}
)+
};
}
with_telegram_observer_variants!(register_middlewares_from_config);
config.outer_middlewares = OuterMiddlewaresConfig::new();
macro_rules! router_constructor {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
Configured {
name: self.name,
sub_routers: self
.sub_routers
.into_iter()
.map(|router| router.configure(config.clone()))
.collect(),
$(
$observer: self.$observer,
)+
startup: self.startup,
shutdown: self.shutdown,
}
};
}
with_telegram_observer_variants!(router_constructor)
}
#[must_use]
pub fn configure_default(self) -> Configured<Client>
where
Client: Send + Sync + 'static,
{
self.configure(Config::default())
}
}
impl<Client> Debug for Router<Client> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Router")
.field("router_name", &self.name)
.field("sub_routers", &self.sub_routers)
.finish_non_exhaustive()
}
}
impl<Client> Default for Router<Client>
where
Client: Send + Sync + 'static,
{
fn default() -> Self {
Self::new("default")
}
}
impl<Client> Clone for Router<Client> {
fn clone(&self) -> Self {
macro_rules! router_construct {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
Self {
name: self.name,
sub_routers: self.sub_routers.clone(),
$(
$observer: self.$observer.clone(),
)+
startup: self.startup.clone(),
shutdown: self.shutdown.clone(),
}
};
}
with_telegram_observer_variants!(router_construct)
}
}
macro_rules! define_configured_struct {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
pub struct Configured<Client = Reqwest> {
name: &'static str,
sub_routers: Vec<Configured<Client>>,
$(
$observer: TelegramObserver<Client>,
)+
pub startup: SimpleObserver,
pub shutdown: SimpleObserver,
}
};
}
with_telegram_observer_variants!(define_configured_struct);
impl<Client> PropagateEvent<Client> for Configured<Client>
where
Client: 'static,
{
#[instrument(skip_all, fields(router = self.name))]
fn propagate_event(
&mut self,
update_type: UpdateType,
mut request: Request<Client>,
) -> impl Future<Output = Result<Response<Client>, EventErrorKind>> + Send
where
Client: Send + Sync + Clone,
{
Box::pin(async move {
match self.propagate_update_event(request).await? {
Response {
request,
propagate_result: PropagateEventResult::Handled(response),
} => {
return Ok(Response {
request,
propagate_result: PropagateEventResult::Handled(response),
});
}
Response {
request,
propagate_result: PropagateEventResult::Rejected,
} => {
return Ok(Response {
request,
propagate_result: PropagateEventResult::Rejected,
});
}
Response {
request: updated_request,
propagate_result: PropagateEventResult::Unhandled,
} => {
request = updated_request;
}
}
event!(Level::TRACE, "Propagate event to router");
let observer = self.telegram_observer_by_update_type(update_type);
for middleware in &mut observer.outer_middlewares.middlewares {
let (updated_request, event_return) = middleware.call(request.clone()).await?;
match event_return {
EventReturn::Finish => {
event!(Level::TRACE, "Outer middleware returns finish");
request = updated_request;
}
EventReturn::Skip => {
event!(Level::TRACE, "Outer middleware returns skip");
}
EventReturn::Cancel => {
event!(Level::TRACE, "Outer middleware returns cancel");
return Ok(Response {
request,
propagate_result: PropagateEventResult::Rejected,
});
}
}
}
let observer_response = observer.trigger(request).await?;
let request = observer_response.request;
match observer_response.propagate_result {
PropagateEventResult::Unhandled => {
event!(Level::TRACE, "Event unhandled by router");
}
PropagateEventResult::Handled(response) => {
event!(Level::TRACE, "Event handled by router");
return Ok(Response {
request,
propagate_result: PropagateEventResult::Handled(response),
});
}
PropagateEventResult::Rejected => {
event!(Level::TRACE, "Event rejected by router");
return Ok(Response {
request,
propagate_result: PropagateEventResult::Unhandled,
});
}
}
for router in &mut self.sub_routers {
let router_response = router.propagate_event(update_type, request.clone()).await?;
match router_response.propagate_result {
PropagateEventResult::Unhandled => {
event!(Level::TRACE, "Event unhandled by sub router");
}
PropagateEventResult::Handled(_) => {
event!(Level::TRACE, "Event handled by sub router");
return Ok(router_response);
}
PropagateEventResult::Rejected => {
event!(Level::TRACE, "Event rejected by sub router");
return Ok(router_response);
}
}
}
Ok(Response {
request,
propagate_result: PropagateEventResult::Unhandled,
})
})
}
#[instrument(skip_all, fields(router = self.name))]
async fn propagate_update_event(
&mut self,
mut request: Request<Client>,
) -> Result<Response<Client>, EventErrorKind>
where
Client: Send + Sync + Clone,
{
event!(Level::TRACE, "Propagate update event to router");
for middleware in &mut self.update.outer_middlewares.middlewares {
let (updated_request, event_return) = middleware.call(request.clone()).await?;
match event_return {
EventReturn::Finish => {
event!(Level::TRACE, "Update outer middleware returns finish");
request = updated_request;
}
EventReturn::Skip => {
event!(Level::TRACE, "Update outer middleware returns skip");
}
EventReturn::Cancel => {
event!(Level::TRACE, "Update outer middleware returns cancel");
return Ok(Response {
request,
propagate_result: PropagateEventResult::Rejected,
});
}
}
}
let observer_response = self.update.trigger(request).await?;
let request = observer_response.request;
match observer_response.propagate_result {
PropagateEventResult::Unhandled => {
event!(Level::TRACE, "Update event unhandled by router");
Ok(Response {
request,
propagate_result: PropagateEventResult::Unhandled,
})
}
PropagateEventResult::Handled(response) => {
event!(Level::TRACE, "Update event handled by router");
Ok(Response {
request,
propagate_result: PropagateEventResult::Handled(response),
})
}
PropagateEventResult::Rejected => {
event!(Level::TRACE, "Update event rejected by router");
Ok(Response {
request,
propagate_result: PropagateEventResult::Unhandled,
})
}
}
}
#[instrument(skip_all, fields(router = self.name))]
async fn emit_startup(&mut self) -> SimpleHandlerResult {
if self.startup.handlers.is_empty() {
event!(Level::TRACE, "Observers empty");
return Ok(());
}
event!(Level::DEBUG, "Start observers");
for startup in once(&mut self.startup).chain(
self.sub_routers
.iter_mut()
.map(|router| &mut router.startup),
) {
if let Err(err) = startup.trigger(()).await {
event!(Level::ERROR, error = %err, "Error while emit observers");
return Err(err);
}
}
Ok(())
}
#[instrument(skip_all, fields(router = self.name))]
async fn emit_shutdown(&mut self) -> SimpleHandlerResult {
if self.shutdown.handlers.is_empty() {
event!(Level::TRACE, "Observers empty");
return Ok(());
}
event!(Level::DEBUG, "Start observers");
for shutdown in once(&mut self.shutdown).chain(
self.sub_routers
.iter_mut()
.map(|router| &mut router.shutdown),
) {
if let Err(err) = shutdown.trigger(()).await {
event!(Level::ERROR, error = %err, "Error while emit observers");
return Err(err);
}
}
Ok(())
}
#[inline]
fn startup_handlers_len(&self) -> usize {
self.startup.handlers_len()
}
#[inline]
fn shutdown_handlers_len(&self) -> usize {
self.startup.handlers_len()
}
}
impl<Client> Configured<Client> {
#[must_use]
#[cfg(test)]
const fn telegram_observers(&self) -> [&TelegramObserver<Client>; 25] {
with_telegram_observer_variants!(observer_refs_array, ref, self)
}
#[must_use]
fn telegram_observer_by_update_type(
&mut self,
update_type: UpdateType,
) -> &mut TelegramObserver<Client> {
macro_rules! by_observer_type_match_arms {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
match TelegramObserverType::from(update_type) {
$(
TelegramObserverType::$variant => &mut self.$observer,
)+
}
};
}
with_telegram_observer_variants!(by_observer_type_match_arms)
}
}
impl<Client> Debug for Configured<Client> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Router")
.field("router_name", &self.name)
.field("sub_routers", &self.sub_routers)
.finish_non_exhaustive()
}
}
impl<Client> Clone for Configured<Client> {
fn clone(&self) -> Self {
macro_rules! router_construct {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
Self {
name: self.name,
sub_routers: self.sub_routers.clone(),
$(
$observer: self.$observer.clone(),
)+
startup: self.startup.clone(),
shutdown: self.shutdown.clone(),
}
};
}
with_telegram_observer_variants!(router_construct)
}
}
impl<Client> Default for Configured<Client>
where
Client: Send + Sync + 'static,
{
fn default() -> Self {
Router::default().configure_default()
}
}
macro_rules! define_middleware_config {
(
$config:ident,
$builder:ident,
$service:ty,
$middleware_trait:ident,
$factory:ident,
{ $($field:ident),+ $(,)? }
, default_builder: $default_builder:expr $(,)?
) => {
pub struct $config<Client> {
$(pub $field: Box<[$service]>,)+
}
impl<Client> $config<Client> {
#[must_use]
pub fn new() -> Self {
Self::builder().build()
}
#[must_use]
pub fn builder() -> $builder<Client> {
$builder::default()
}
}
impl<Client> Clone for $config<Client> {
fn clone(&self) -> Self {
Self {
$($field: self.$field.clone(),)+
}
}
}
impl<Client: Send + Sync + 'static> Default for $config<Client> {
fn default() -> Self {
$default_builder(Default::default()).build()
}
}
pub struct $builder<Client> {
$(pub $field: Vec<$service>,)+
}
impl<Client: Send + Sync + 'static> $builder<Client> {
$(
#[doc = concat!("Adds a middleware to the `", stringify!($field), "` observser")]
#[must_use]
pub fn $field(mut self, val: impl $middleware_trait<Client>) -> Self {
self.$field.push($factory(val));
self
}
)+
#[doc = "Adds the same middleware to all Telegram observsers"]
#[must_use]
pub fn all(mut self, middleware: impl $middleware_trait<Client>) -> Self {
$(
self = self.$field(middleware.clone());
)+
self
}
}
impl<Client> $builder<Client> {
#[must_use]
pub fn build(self) -> $config<Client> {
$config {
$($field: self.$field.into(),)+
}
}
}
impl<Client> Default for $builder<Client> {
fn default() -> Self {
Self {
$($field: vec![],)+
}
}
}
}
}
macro_rules! define_outer_middleware_config_for_observers {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
define_middleware_config!(
OuterMiddlewaresConfig,
OuterMiddlewaresConfigBuilder,
BoxedCloneOuterMiddlewareService<Client>,
OuterMiddleware,
boxed_outer_middleware_factory,
{ $($observer,)+ },
default_builder: |builder: OuterMiddlewaresConfigBuilder<Client>| builder.update(UserContextMiddleware),
);
};
}
with_telegram_observer_variants!(define_outer_middleware_config_for_observers);
macro_rules! define_inner_middleware_config_for_observers {
($(($variant:ident, $observer:ident)),+ $(,)?) => {
define_middleware_config!(
InnerMiddlewaresConfig,
InnerMiddlewaresConfigBuilder,
BoxedCloneInnerMiddlewareService<Client>,
InnerMiddleware,
boxed_inner_middleware_factory,
{ $($observer,)+ },
default_builder: |builder: InnerMiddlewaresConfigBuilder<Client>| builder.all(LoggingMiddleware),
);
};
}
with_telegram_observer_variants!(define_inner_middleware_config_for_observers);
pub struct Config<Client> {
outer_middlewares: OuterMiddlewaresConfig<Client>,
inner_middlewares: InnerMiddlewaresConfig<Client>,
}
impl<Client> Config<Client> {
#[must_use]
pub const fn new(
outer_middlewares: OuterMiddlewaresConfig<Client>,
inner_middlewares: InnerMiddlewaresConfig<Client>,
) -> Self {
Self {
outer_middlewares,
inner_middlewares,
}
}
}
impl<Client> Default for Config<Client>
where
Client: Send + Sync + 'static,
{
fn default() -> Self {
Self {
outer_middlewares: OuterMiddlewaresConfig::default(),
inner_middlewares: InnerMiddlewaresConfig::default(),
}
}
}
impl<Client> Clone for Config<Client> {
fn clone(&self) -> Self {
Self {
outer_middlewares: self.outer_middlewares.clone(),
inner_middlewares: self.inner_middlewares.clone(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
client::Reqwest,
event::{
simple::Handler as SimpleHandler,
telegram::{Handler as TelegramHandler, HandlerResult as TelegramHandlerResult},
EventReturn,
},
middlewares::Next,
types::{ChatPrivate, MessageText, Update, UpdateMessage},
Bot, Context, Extensions,
};
use std::{convert::Infallible, sync::Arc};
use tokio;
#[test]
fn test_include_router() {
let inner_middleware = |request, next: Next<_>| next(request);
let outer_middleware = |request| async move { Ok((request, EventReturn::default())) };
let router = Router::<Reqwest>::new("main")
.on_message(|observer| {
observer
.register_inner_middleware(inner_middleware)
.register_outer_middleware(outer_middleware)
})
.include(
Router::new("sub1")
.include(Router::new("sub1.1"))
.include(Router::new("sub1.2")),
)
.include(
Router::new("sub2")
.include(Router::new("sub2.1"))
.include(Router::new("sub2.2")),
)
.include(
Router::new("sub3")
.include(Router::new("sub3.1"))
.include(Router::new("sub3.2")),
);
let router_configured = router.configure(Config::new(
OuterMiddlewaresConfig::new(),
InnerMiddlewaresConfig::new(),
));
assert_eq!(router_configured.sub_routers.len(), 3);
assert_eq!(router_configured.name, "main");
let message_observer_name = UpdateType::Message.as_ref();
router_configured
.sub_routers
.iter()
.for_each(|router_configured| {
assert_eq!(router_configured.sub_routers.len(), 2);
router_configured
.telegram_observers()
.into_iter()
.for_each(|observer| {
if observer.event_name == message_observer_name {
assert_eq!(observer.inner_middlewares.middlewares.len(), 1);
} else {
assert_eq!(observer.inner_middlewares.middlewares.len(), 0);
}
assert_eq!(observer.outer_middlewares.middlewares.len(), 0);
});
router_configured
.sub_routers
.iter()
.for_each(|router_configured| {
assert_eq!(router_configured.sub_routers.len(), 0);
router_configured
.telegram_observers()
.into_iter()
.for_each(|observer| {
if observer.event_name == message_observer_name {
assert_eq!(observer.inner_middlewares.middlewares.len(), 1);
} else {
assert_eq!(observer.inner_middlewares.middlewares.len(), 0);
}
assert_eq!(observer.outer_middlewares.middlewares.len(), 0);
});
});
});
}
#[rustfmt::skip]
#[test]
fn test_observer_register() {
async fn telegram_handler() -> TelegramHandlerResult {
Ok(EventReturn::Finish)
}
async fn simple_handler() -> SimpleHandlerResult {
Ok(())
}
let mut router = Router::<Reqwest>::new("main")
.on_all(|observer| observer.register(TelegramHandler::new(telegram_handler)))
.on_startup(|observer| observer.register(SimpleHandler::new(simple_handler, ())))
.on_shutdown(|observer| observer.register(SimpleHandler::new(simple_handler, ())));
router
.telegram_observers()
.into_iter()
.for_each(|observer| {
assert_eq!(observer.handlers.len(), 1);
observer.handlers.iter().for_each(|handler| {
assert!(handler.filters.is_empty());
});
});
router.event_observers().into_iter().for_each(|observer| {
assert_eq!(observer.handlers.len(), 1);
});
let inner_middleware = |request, next: Next| next(request);
let outer_middleware = |request| async move { Ok((request, EventReturn::Finish)) };
router = router.on_message(|observer| {
observer
.register_inner_middleware(inner_middleware)
.register_outer_middleware(outer_middleware)
});
let message_observer = router
.telegram_observers()
.into_iter()
.find(|observer| observer.event_name == UpdateType::Message.as_ref())
.unwrap();
assert_eq!(message_observer.inner_middlewares.middlewares.len(), 1);
assert_eq!(message_observer.outer_middlewares.middlewares.len(), 1);
}
#[tokio::test]
async fn test_propagate_event() {
let request = Request::<Reqwest> {
update: Arc::new(Update::Message(UpdateMessage::new(
0,
MessageText::new(0, 0, ChatPrivate::new(0), ""),
))),
bot: Bot::default(),
context: crate::Context::default(),
extensions: Extensions::default(),
};
let router = Router::new("test_handler").on_message(|observer| {
observer.register(TelegramHandler::new(|| async move {
Ok::<_, Infallible>(EventReturn::Finish)
}))
});
let mut router_configured = router.configure_default();
let response = router_configured
.propagate_event(UpdateType::Message, request.clone())
.await
.unwrap();
match response.propagate_result {
PropagateEventResult::Handled(response) => match response.result {
Ok(EventReturn::Finish) => {}
_ => panic!("Unexpected result"),
},
_ => panic!("Unexpected result"),
}
let response = router_configured
.propagate_event(UpdateType::CallbackQuery, request.clone())
.await
.unwrap();
match response.propagate_result {
PropagateEventResult::Unhandled => {}
_ => panic!("Unexpected result"),
}
let router = Router::new("test_middleware_and_handler")
.on_update(|observer| {
observer.register_outer_middleware(|mut request: Request<Reqwest>| async move {
request.context.insert("test", "test");
Ok((request, EventReturn::Finish))
})
})
.on_message(|observer| {
observer.register(TelegramHandler::new(|context: Context| async move {
println!("{}", context.len());
assert_eq!(context.get::<&str>("test").unwrap(), &"test");
Ok::<_, Infallible>(EventReturn::Finish)
}))
});
let mut router_configured = router.configure_default();
let response = router_configured
.propagate_event(UpdateType::Message, request.clone())
.await
.unwrap();
match response.propagate_result {
PropagateEventResult::Handled(response) => match response.result {
Ok(EventReturn::Finish) => {}
_ => panic!("Unexpected result"),
},
_ => panic!("Unexpected result"),
}
let router = Router::new("test_skip_handler")
.on_message(|observer| {
observer.register(TelegramHandler::new(|| async move {
Ok::<_, Infallible>(EventReturn::Skip)
}))
})
.on_message(|observer| {
observer.register(TelegramHandler::new(|| async move {
Ok::<_, Infallible>(EventReturn::Finish)
}))
});
let mut router_configured = router.configure_default();
let response = router_configured
.propagate_event(UpdateType::Message, request.clone())
.await
.unwrap();
match response.propagate_result {
PropagateEventResult::Handled(response) => match response.result {
Ok(EventReturn::Finish) => {}
_ => panic!("Unexpected result"),
},
_ => panic!("Unexpected result"),
}
let router = Router::new("test_skip_handler_without_next").on_message(|observer| {
observer.register(TelegramHandler::new(|| async move {
Ok::<_, Infallible>(EventReturn::Skip)
}))
});
let mut router_configured = router.configure_default();
let response = router_configured
.propagate_event(UpdateType::Message, request.clone())
.await
.unwrap();
match response.propagate_result {
PropagateEventResult::Unhandled => {}
_ => panic!("Unexpected result"),
}
}
#[tokio::test]
async fn test_propagate_event_with_filter() {
let request = Request::<Reqwest> {
update: Arc::new(Update::Message(UpdateMessage::new(
0,
MessageText::new(0, 0, ChatPrivate::new(0), ""),
))),
bot: Bot::default(),
context: crate::Context::default(),
extensions: Extensions::default(),
};
let router = Router::new("test_handler_with_filter").on_message(|observer| {
observer.register(
TelegramHandler::new(|| async move { Ok::<_, Infallible>(EventReturn::Finish) })
.filter(|_req: &mut Request| async move { Ok::<_, Infallible>(true) }),
)
});
let mut router_configured = router.configure_default();
let response = router_configured
.propagate_event(UpdateType::Message, request.clone())
.await
.unwrap();
match response.propagate_result {
PropagateEventResult::Handled(response) => match response.result {
Ok(EventReturn::Finish) => {}
_ => panic!("Unexpected result"),
},
_ => panic!("Unexpected result"),
}
let router = Router::new("test_handler_with_fail_filter").on_message(|observer| {
observer.register(
TelegramHandler::new(|| async move { Ok::<_, Infallible>(EventReturn::Finish) })
.filter(|_req: &mut Request| async move { Ok::<_, Infallible>(false) }),
)
});
let mut router_configured = router.configure_default();
let response = router_configured
.propagate_event(UpdateType::Message, request.clone())
.await
.unwrap();
match response.propagate_result {
PropagateEventResult::Unhandled => {}
_ => panic!("Unexpected result"),
}
let router = Router::new("test_handler_with_filters_and_one_fail").on_message(|observer| {
observer.register(
TelegramHandler::new(|| async move { Ok::<_, Infallible>(EventReturn::Finish) })
.filter(|_req: &mut Request| async move { Ok::<_, Infallible>(true) })
.filter(|_req: &mut Request| async move { Ok::<_, Infallible>(true) })
.filter(|_req: &mut Request| async move { Ok::<_, Infallible>(false) }),
)
});
let mut router_configured = router.configure_default();
let response = router_configured
.propagate_event(UpdateType::Message, request.clone())
.await
.unwrap();
match response.propagate_result {
PropagateEventResult::Unhandled => {}
_ => panic!("Unexpected result"),
}
}
#[test]
fn test_resolve_used_update_types() {
let router = Router::<Reqwest>::new("test")
.on_message(|observer| {
observer.register(TelegramHandler::new(|| async {
Ok::<_, Infallible>(EventReturn::Finish)
}))
})
.on_edited_message(|observer| {
observer.register(TelegramHandler::new(|| async {
Ok::<_, Infallible>(EventReturn::Finish)
}))
});
let update_types = router.resolve_used_update_types();
assert_eq!(update_types.len(), 2);
assert!(update_types.contains(UpdateType::Message.as_ref()));
assert!(update_types.contains(UpdateType::EditedMessage.as_ref()));
let router2 = Router::<Reqwest>::new("test2")
.on_message(|observer| {
observer.register(TelegramHandler::new(|| async {
Ok::<_, Infallible>(EventReturn::Finish)
}))
})
.on_channel_post(|observer| {
observer.register(TelegramHandler::new(|| async {
Ok::<_, Infallible>(EventReturn::Finish)
}))
});
assert_eq!(router2.resolve_used_update_types().len(), 2);
let router = router.include(router2);
let update_types = router.resolve_used_update_types();
println!("{update_types:?}");
assert_eq!(update_types.len(), 3);
assert!(update_types.contains(UpdateType::Message.as_ref()));
assert!(update_types.contains(UpdateType::EditedMessage.as_ref()));
assert!(update_types.contains(UpdateType::ChannelPost.as_ref()));
let update_types =
router.resolve_used_update_types_with_skip([UpdateType::Message.as_ref()]);
assert_eq!(update_types.len(), 2);
assert!(update_types.contains(UpdateType::EditedMessage.as_ref()));
assert!(update_types.contains(UpdateType::ChannelPost.as_ref()));
}
struct DummyClient;
#[test]
fn test_outer_middlewares_config_default() {
let config = OuterMiddlewaresConfig::<DummyClient>::default();
assert_eq!(config.update.len(), 1);
assert_eq!(config.message.len(), 0);
assert_eq!(config.edited_message.len(), 0);
}
#[test]
fn test_inner_middlewares_config_default() {
let config = InnerMiddlewaresConfig::<DummyClient>::default();
assert_eq!(config.message.len(), 1);
assert_eq!(config.edited_message.len(), 1);
assert_eq!(config.callback_query.len(), 1);
}
#[test]
fn test_middlewares_config_default() {
let config = Config::<DummyClient>::default();
assert_eq!(config.outer_middlewares.update.len(), 1);
assert_eq!(config.outer_middlewares.message.len(), 0);
assert_eq!(config.outer_middlewares.edited_message.len(), 0);
assert_eq!(config.inner_middlewares.message.len(), 1);
assert_eq!(config.inner_middlewares.edited_message.len(), 1);
assert_eq!(config.inner_middlewares.callback_query.len(), 1);
}
}