ferrisgram 0.2.1

An elegent rust client for the Telegram Bot API.
Documentation
use crate::error::{Error, GroupIteration};
use crate::ext::{Context, Handler};
use crate::types::Update;
use crate::Bot;
use GroupIteration::{ContinueGroups, EndGroups, ResumeGroups};

type ErrorHandlerFunc = fn(&Bot, &Context, Error) -> GroupIteration;

#[derive(Clone)]
pub struct Dispatcher<'a> {
    pub bot: &'a Bot,
    handler_groups: Vec<i32>,
    handlers: Vec<HandlersGroup>,
    error_handler: ErrorHandlerFunc,
}

#[derive(Clone)]
struct HandlersGroup {
    pub handler_group: i32,
    pub handlers: Vec<Box<dyn Handler>>,
}

impl HandlersGroup {
    fn new(group: i32) -> Self {
        Self {
            handler_group: group,
            handlers: Vec::new(),
        }
    }
}

#[allow(unused_must_use)]
impl<'a> Dispatcher<'a> {
    pub fn new(bot: &'a Bot) -> Self {
        Self {
            bot,
            handler_groups: Vec::new(),
            handlers: Vec::new(),
            error_handler: Self::default_error_handler,
        }
    }

    pub fn add_handler_to_group(&mut self, handler_trait: Box<dyn Handler>, handler_group: i32) {
        if !self.handler_groups.contains(&handler_group) {
            self.handler_groups.push(handler_group);
            self.handlers.push(HandlersGroup::new(handler_group))
        }
        let mut handlers = Vec::new();
        for mut hg in self.handlers.clone() {
            if hg.handler_group == handler_group {
                hg.handlers.push(handler_trait.clone())
            }
            handlers.push(hg)
        }
        self.handlers = handlers;
        self.handler_groups.sort_unstable()
    }
    pub fn add_handler(&mut self, handler: Box<dyn Handler>) {
        self.add_handler_to_group(handler, 0)
    }
    pub fn add_error_handler(&mut self, error_hander: ErrorHandlerFunc) {
        self.error_handler = error_hander
    }
    pub async fn process_update(&mut self, update: &Update) -> tokio::task::JoinHandle<()> {
        let handler_groups = self.handler_groups.clone();
        let handlers = self.handlers.clone();
        let error_handler = self.error_handler;
        let bot = self.bot.clone();
        let update = update.clone();
        tokio::spawn(async move {
            let ctx = Context::new(&update);
            for group in handler_groups.iter() {
                for handler in handlers.iter() {
                    if &handler.handler_group == group {
                        for handler in handler.handlers.iter() {
                            if !handler.check_update(&bot, &update).await {
                                continue;
                            }
                            let res = handler.handle_update(&bot, &ctx).await;
                            match res {
                                Ok(mode) => match mode {
                                    EndGroups => return,
                                    ContinueGroups => break,
                                    ResumeGroups => continue,
                                },
                                Err(error) => {
                                    (error_handler)(&bot, &ctx, error);
                                }
                            }
                        }
                    }
                }
            }
        })
    }
    fn default_error_handler(_: &Bot, _: &Context, error: Error) -> GroupIteration {
        println!("{}", error);
        ResumeGroups
    }
}