mod callbacks; mod commands; mod markups; mod master_password_check; mod state; mod utils; use sea_orm::prelude::*; use std::sync::Arc; use teloxide::{ adaptors::{throttle::Limits, Throttle}, dispatching::dialogue::InMemStorage, filter_command, prelude::*, utils::command::BotCommands, }; use tokio::sync::Mutex; type MainDialogue = Dialogue>; #[allow(clippy::type_complexity)] pub struct Handler { pub handler: Box< dyn FnOnce( Throttle, Message, DatabaseConnection, MainDialogue, T, ) -> crate::PinnedFuture<'static, crate::Result<()>> + Send + Sync, >, pub previous: Option, } type PackagedHandler = Arc>>>; #[derive(BotCommands, Clone, Copy)] #[command( rename_rule = "snake_case", description = "These commands are supported:" )] enum Command { #[command(description = "displays the welcome message")] Start, #[command(description = "displays this text")] Help, #[command(description = "sets the master password")] SetMasterPass, #[command(description = "adds the account")] AddAccount, #[command(description = "gets the account")] GetAccount, #[command(description = "gets a list of accounts")] GetAccounts, #[command(description = "deletes the account")] Delete, #[command(description = "deletes all the accounts and the master password")] DeleteAll, #[command(description = "exports all the accounts in a json file")] Export, #[command(description = "loads the accounts from a json file")] Import, #[command(description = "generates 10 secure passwords")] GenPassword, #[command(description = "cancels the current action")] Cancel, } #[derive(Default, Clone)] pub enum State { #[default] Start, GetAccountName(PackagedHandler), GetMasterPass(PackagedHandler), GetLogin(PackagedHandler), GetPassword(PackagedHandler), GetDocument(PackagedHandler<()>), } pub fn get_dispatcher( token: String, db: DatabaseConnection, ) -> Dispatcher, crate::Error, teloxide::dispatching::DefaultKey> { use dptree::{case, deps, endpoint}; let bot = Bot::new(token).throttle(Limits::default()); let command_handler = filter_command::() .branch(case![Command::Start].endpoint(commands::start)) .branch(case![Command::Help].endpoint(commands::help)) .branch(case![Command::SetMasterPass].endpoint(commands::set_master_pass)) .branch(case![Command::GenPassword].endpoint(commands::gen_password)) .branch(case![Command::Cancel].endpoint(commands::cancel)) // This branch filters out the users that don't have a master password set .branch(master_password_check::get_handler()) .branch(case![Command::AddAccount].endpoint(commands::add_account)) .branch(case![Command::GetAccount].endpoint(commands::get_account)) .branch(case![Command::GetAccounts].endpoint(commands::get_accounts)) .branch(case![Command::Delete].endpoint(commands::delete)) .branch(case![Command::DeleteAll].endpoint(commands::delete_all)) .branch(case![Command::Export].endpoint(commands::export)) .branch(case![Command::Import].endpoint(commands::import)); let message_handler = Update::filter_message() .map_async(utils::delete_message) .enter_dialogue::, State>() .branch(case![State::GetAccountName(next)].endpoint(state::get_account_name)) .branch(case![State::GetMasterPass(next)].endpoint(state::get_master_pass)) .branch(case![State::GetLogin(next)].endpoint(state::get_login)) .branch(case![State::GetPassword(next)].endpoint(state::get_password)) .branch(case![State::GetDocument(next)].endpoint(state::get_document)) .branch(command_handler) .branch(endpoint(commands::default)); let callback_handler = Update::filter_callback_query().chain(callbacks::delete_message::get_handler()); let handler = dptree::entry() .branch(message_handler) .branch(callback_handler); Dispatcher::builder(bot, handler) .dependencies(deps![db, InMemStorage::::new()]) .enable_ctrlc_handler() .build() }