Fix the error

This commit is contained in:
Temirkhan Myrzamadi 2020-01-29 20:48:57 +06:00
parent 84d4e6fb2c
commit 3bad400c03
4 changed files with 151 additions and 62 deletions

View file

@ -16,52 +16,55 @@ use futures::StreamExt;
use std::fmt::Debug; use std::fmt::Debug;
pub struct BasicHandlerCtx<'a, Upd> { pub struct BasicHandlerCtx<'a, Upd> {
bot: &'a Bot, pub bot: &'a Bot,
update: Upd, pub update: Upd,
} }
pub struct Dispatcher<'a, Session1, Session2, H1, H2, HandlerE> { pub struct Dispatcher<'a, Session1, Session2, H1, H2, HandlerE> {
bot: &'a Bot, bot: &'a Bot,
handlers_error_handler: Box<dyn Handler<HandlerE, ()>>, handlers_error_handler: Box<dyn Handler<HandlerE, ()> + 'a>,
private_message_dp: Option<SessionDispatcher<'a, Session1, H1>>, private_message_dp: Option<SessionDispatcher<'a, Session1, H1>>,
private_edited_message_dp: Option<SessionDispatcher<'a, Session2, H2>>, private_edited_message_dp: Option<SessionDispatcher<'a, Session2, H2>>,
message_handler: Option<Box<dyn Handler<BasicHandlerCtx<'a, Message>, ()>>>, message_handler:
Option<Box<dyn Handler<BasicHandlerCtx<'a, Message>, ()> + 'a>>,
edited_message_handler: edited_message_handler:
Option<Box<dyn Handler<BasicHandlerCtx<'a, Message>, ()>>>, Option<Box<dyn Handler<BasicHandlerCtx<'a, Message>, ()> + 'a>>,
channel_post_handler: channel_post_handler:
Option<Box<dyn Handler<BasicHandlerCtx<'a, Message>, ()>>>, Option<Box<dyn Handler<BasicHandlerCtx<'a, Message>, ()> + 'a>>,
edited_channel_post_handler: edited_channel_post_handler:
Option<Box<dyn Handler<BasicHandlerCtx<'a, Message>, ()>>>, Option<Box<dyn Handler<BasicHandlerCtx<'a, Message>, ()> + 'a>>,
inline_query_handler: inline_query_handler:
Option<Box<dyn Handler<BasicHandlerCtx<'a, InlineQuery>, ()>>>, Option<Box<dyn Handler<BasicHandlerCtx<'a, InlineQuery>, ()> + 'a>>,
chosen_inline_result_handler: chosen_inline_result_handler: Option<
Option<Box<dyn Handler<BasicHandlerCtx<'a, ChosenInlineResult>, ()>>>, Box<dyn Handler<BasicHandlerCtx<'a, ChosenInlineResult>, ()> + 'a>,
>,
callback_query_handler: callback_query_handler:
Option<Box<dyn Handler<BasicHandlerCtx<'a, CallbackQuery>, ()>>>, Option<Box<dyn Handler<BasicHandlerCtx<'a, CallbackQuery>, ()> + 'a>>,
shipping_query_handler: shipping_query_handler:
Option<Box<dyn Handler<BasicHandlerCtx<'a, ShippingQuery>, ()>>>, Option<Box<dyn Handler<BasicHandlerCtx<'a, ShippingQuery>, ()> + 'a>>,
pre_checkout_query_handler: pre_checkout_query_handler: Option<
Option<Box<dyn Handler<BasicHandlerCtx<'a, PreCheckoutQuery>, ()>>>, Box<dyn Handler<BasicHandlerCtx<'a, PreCheckoutQuery>, ()> + 'a>,
poll_handler: Option<Box<dyn Handler<BasicHandlerCtx<'a, Poll>, ()>>>, >,
poll_handler: Option<Box<dyn Handler<BasicHandlerCtx<'a, Poll>, ()> + 'a>>,
} }
impl<'a, Session1, Session2, H1, H2, HandlerE> impl<'a, Session1, Session2, H1, H2, HandlerE>
Dispatcher<'a, Session1, Session2, H1, H2, HandlerE> Dispatcher<'a, Session1, Session2, H1, H2, HandlerE>
where where
Session1: Default, Session1: Default + 'a,
Session2: Default, Session2: Default + 'a,
H1: Handler< H1: Handler<
SessionHandlerCtx<'a, Message, Session1>, SessionHandlerCtx<'a, Message, Session1>,
SessionState<Session1>, SessionState<Session1>,
>, > + 'a,
H2: Handler< H2: Handler<
SessionHandlerCtx<'a, Message, Session2>, SessionHandlerCtx<'a, Message, Session2>,
SessionState<Session2>, SessionState<Session2>,
>, > + 'a,
HandlerE: Debug, HandlerE: Debug + 'a,
{ {
pub fn new(bot: &'a Bot) -> Self { pub fn new(bot: &'a Bot) -> Self {
Self { Self {
@ -82,6 +85,14 @@ where
} }
} }
pub fn handlers_error_handler<T>(mut self, val: T) -> Self
where
T: Handler<HandlerE, ()> + 'a,
{
self.handlers_error_handler = Box::new(val);
self
}
pub fn private_message_dp( pub fn private_message_dp(
mut self, mut self,
dp: SessionDispatcher<'a, Session1, H1>, dp: SessionDispatcher<'a, Session1, H1>,
@ -90,37 +101,115 @@ where
self self
} }
async fn dispatch(&'a mut self) pub fn private_edited_message_dp(
mut self,
dp: SessionDispatcher<'a, Session2, H2>,
) -> Self {
self.private_edited_message_dp = Some(dp);
self
}
pub fn message_handler<H>(mut self, h: H) -> Self
where where
Session1: 'a, H: Handler<BasicHandlerCtx<'a, Message>, ()> + 'a,
Session2: 'a,
H1: 'a,
H2: 'a,
HandlerE: 'a,
{ {
self.message_handler = Some(Box::new(h));
self
}
pub fn edited_message_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, Message>, ()> + 'a,
{
self.edited_message_handler = Some(Box::new(h));
self
}
pub fn channel_post_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, Message>, ()> + 'a,
{
self.channel_post_handler = Some(Box::new(h));
self
}
pub fn edited_channel_post_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, Message>, ()> + 'a,
{
self.edited_channel_post_handler = Some(Box::new(h));
self
}
pub fn inline_query_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, InlineQuery>, ()> + 'a,
{
self.inline_query_handler = Some(Box::new(h));
self
}
pub fn chosen_inline_result_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, ChosenInlineResult>, ()> + 'a,
{
self.chosen_inline_result_handler = Some(Box::new(h));
self
}
pub fn callback_query_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, CallbackQuery>, ()> + 'a,
{
self.callback_query_handler = Some(Box::new(h));
self
}
pub fn shipping_query_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, ShippingQuery>, ()> + 'a,
{
self.shipping_query_handler = Some(Box::new(h));
self
}
pub fn pre_checkout_query_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, PreCheckoutQuery>, ()> + 'a,
{
self.pre_checkout_query_handler = Some(Box::new(h));
self
}
pub fn poll_handler<H>(mut self, h: H) -> Self
where
H: Handler<BasicHandlerCtx<'a, Poll>, ()> + 'a,
{
self.poll_handler = Some(Box::new(h));
self
}
pub async fn dispatch(&'a mut self) {
self.dispatch_with_listener( self.dispatch_with_listener(
update_listeners::polling_default(self.bot), update_listeners::polling_default(self.bot),
error_handlers::Log, &error_handlers::Log,
) )
.await; .await;
} }
async fn dispatch_with_listener<UListener, ListenerE, Eh>( pub async fn dispatch_with_listener<UListener, ListenerE, Eh>(
&'a mut self, &'a self,
update_listener: UListener, update_listener: UListener,
update_listener_error_handler: Eh, update_listener_error_handler: &'a Eh,
) where ) where
UListener: UpdateListener<ListenerE> + 'a, UListener: UpdateListener<ListenerE> + 'a,
Eh: Handler<ListenerE, ()> + 'a, Eh: Handler<ListenerE, ()> + 'a,
Session1: 'a,
Session2: 'a,
H1: 'a,
H2: 'a,
HandlerE: 'a,
ListenerE: Debug, ListenerE: Debug,
{ {
let update_listener = Box::pin(update_listener);
update_listener update_listener
.for_each_concurrent(None, move |update| async { .for_each_concurrent(None, move |update| async move {
let update = match update { let update = match update {
Ok(update) => update, Ok(update) => update,
Err(error) => { Err(error) => {
@ -133,7 +222,7 @@ where
UpdateKind::Message(message) => match message.chat.kind { UpdateKind::Message(message) => match message.chat.kind {
ChatKind::Private { .. } => { ChatKind::Private { .. } => {
if let Some(private_message_dp) = if let Some(private_message_dp) =
&mut self.private_message_dp &self.private_message_dp
{ {
private_message_dp private_message_dp
.dispatch(self.bot, message) .dispatch(self.bot, message)
@ -141,8 +230,7 @@ where
} }
} }
_ => { _ => {
if let Some(message_handler) = if let Some(message_handler) = &self.message_handler
&mut self.message_handler
{ {
message_handler message_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -158,7 +246,7 @@ where
match message.chat.kind { match message.chat.kind {
ChatKind::Private { .. } => { ChatKind::Private { .. } => {
if let Some(private_edited_message_dp) = if let Some(private_edited_message_dp) =
&mut self.private_edited_message_dp &self.private_edited_message_dp
{ {
private_edited_message_dp private_edited_message_dp
.dispatch(self.bot, message) .dispatch(self.bot, message)
@ -167,7 +255,7 @@ where
} }
_ => { _ => {
if let Some(edited_message_handler) = if let Some(edited_message_handler) =
&mut self.edited_message_handler &self.edited_message_handler
{ {
edited_message_handler edited_message_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -181,7 +269,7 @@ where
} }
UpdateKind::ChannelPost(post) => { UpdateKind::ChannelPost(post) => {
if let Some(channel_post_handler) = if let Some(channel_post_handler) =
&mut self.channel_post_handler &self.channel_post_handler
{ {
channel_post_handler channel_post_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -193,7 +281,7 @@ where
} }
UpdateKind::EditedChannelPost(post) => { UpdateKind::EditedChannelPost(post) => {
if let Some(edited_channel_post_handler) = if let Some(edited_channel_post_handler) =
&mut self.edited_channel_post_handler &self.edited_channel_post_handler
{ {
edited_channel_post_handler edited_channel_post_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -205,7 +293,7 @@ where
} }
UpdateKind::InlineQuery(query) => { UpdateKind::InlineQuery(query) => {
if let Some(inline_query_handler) = if let Some(inline_query_handler) =
&mut self.inline_query_handler &self.inline_query_handler
{ {
inline_query_handler inline_query_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -217,7 +305,7 @@ where
} }
UpdateKind::ChosenInlineResult(result) => { UpdateKind::ChosenInlineResult(result) => {
if let Some(chosen_inline_result_handler) = if let Some(chosen_inline_result_handler) =
&mut self.chosen_inline_result_handler &self.chosen_inline_result_handler
{ {
chosen_inline_result_handler chosen_inline_result_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -229,7 +317,7 @@ where
} }
UpdateKind::CallbackQuery(query) => { UpdateKind::CallbackQuery(query) => {
if let Some(callback_query_handler) = if let Some(callback_query_handler) =
&mut self.callback_query_handler &self.callback_query_handler
{ {
callback_query_handler callback_query_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -241,7 +329,7 @@ where
} }
UpdateKind::ShippingQuery(query) => { UpdateKind::ShippingQuery(query) => {
if let Some(shipping_query_handler) = if let Some(shipping_query_handler) =
&mut self.shipping_query_handler &self.shipping_query_handler
{ {
shipping_query_handler shipping_query_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -253,7 +341,7 @@ where
} }
UpdateKind::PreCheckoutQuery(query) => { UpdateKind::PreCheckoutQuery(query) => {
if let Some(pre_checkout_query_handler) = if let Some(pre_checkout_query_handler) =
&mut self.pre_checkout_query_handler &self.pre_checkout_query_handler
{ {
pre_checkout_query_handler pre_checkout_query_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
@ -264,7 +352,7 @@ where
} }
} }
UpdateKind::Poll(poll) => { UpdateKind::Poll(poll) => {
if let Some(poll_handler) = &mut self.poll_handler { if let Some(poll_handler) = &self.poll_handler {
poll_handler poll_handler
.handle(BasicHandlerCtx { .handle(BasicHandlerCtx {
bot: self.bot, bot: self.bot,

View file

@ -84,7 +84,7 @@ where
} }
/// Dispatches a single `message` from a private chat. /// Dispatches a single `message` from a private chat.
pub async fn dispatch<Upd>(&'a mut self, bot: &'a Bot, update: Upd) pub async fn dispatch<Upd>(&'a self, bot: &'a Bot, update: Upd)
where where
H: Handler<SessionHandlerCtx<'a, Upd, Session>, SessionState<Session>>, H: Handler<SessionHandlerCtx<'a, Upd, Session>, SessionState<Session>>,
Upd: GetChatId, Upd: GetChatId,

View file

@ -2,6 +2,7 @@ use async_trait::async_trait;
use super::Storage; use super::Storage;
use std::collections::HashMap; use std::collections::HashMap;
use tokio::sync::Mutex;
/// A memory storage based on a hash map. Stores all the sessions directly in /// A memory storage based on a hash map. Stores all the sessions directly in
/// RAM. /// RAM.
@ -10,23 +11,23 @@ use std::collections::HashMap;
/// All the sessions will be lost after you restart your bot. If you need to /// All the sessions will be lost after you restart your bot. If you need to
/// store them somewhere on a drive, you need to implement a storage /// store them somewhere on a drive, you need to implement a storage
/// communicating with a DB. /// communicating with a DB.
#[derive(Clone, Debug, Eq, PartialEq, Default)] #[derive(Debug, Default)]
pub struct InMemStorage<Session> { pub struct InMemStorage<Session> {
map: HashMap<i64, Session>, map: Mutex<HashMap<i64, Session>>,
} }
#[async_trait(?Send)] #[async_trait(?Send)]
#[async_trait] #[async_trait]
impl<Session> Storage<Session> for InMemStorage<Session> { impl<Session> Storage<Session> for InMemStorage<Session> {
async fn remove_session(&mut self, chat_id: i64) -> Option<Session> { async fn remove_session(&self, chat_id: i64) -> Option<Session> {
self.map.remove(&chat_id) self.map.lock().await.remove(&chat_id)
} }
async fn update_session( async fn update_session(
&mut self, &self,
chat_id: i64, chat_id: i64,
state: Session, state: Session,
) -> Option<Session> { ) -> Option<Session> {
self.map.insert(chat_id, state) self.map.lock().await.insert(chat_id, state)
} }
} }

View file

@ -18,14 +18,14 @@ pub trait Storage<Session> {
/// ///
/// Returns `None` if there wasn't such a session, `Some(session)` if a /// Returns `None` if there wasn't such a session, `Some(session)` if a
/// `session` was deleted. /// `session` was deleted.
async fn remove_session(&mut self, chat_id: i64) -> Option<Session>; async fn remove_session(&self, chat_id: i64) -> Option<Session>;
/// Updates a session with the specified `chat_id`. /// Updates a session with the specified `chat_id`.
/// ///
/// Returns `None` if there wasn't such a session, `Some(session)` if a /// Returns `None` if there wasn't such a session, `Some(session)` if a
/// `session` was updated. /// `session` was updated.
async fn update_session( async fn update_session(
&mut self, &self,
chat_id: i64, chat_id: i64,
session: Session, session: Session,
) -> Option<Session>; ) -> Option<Session>;