added get endpoint, updated state_management
This commit is contained in:
parent
96c7d2e37e
commit
22c754a256
@ -1,7 +1,7 @@
|
|||||||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
|
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
|
||||||
|
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use sea_orm::{entity::prelude::*, QueryOrder, QuerySelect};
|
use sea_orm::{entity::prelude::*, QueryOrder, QuerySelect, Statement};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "account")]
|
#[sea_orm(table_name = "account")]
|
||||||
@ -86,4 +86,20 @@ impl Entity {
|
|||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a name by a hex of a SHA256 hash of the name
|
||||||
|
pub async fn get_name_by_hash(
|
||||||
|
user_id: u64,
|
||||||
|
hash: String,
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
) -> crate::Result<Option<String>> {
|
||||||
|
db.query_one(Statement::from_sql_and_values(
|
||||||
|
sea_orm::DatabaseBackend::MySql,
|
||||||
|
"SELECT `name` FROM `account` WHERE SHA2(`name`, 256) = ? AND `user_id` = ?;",
|
||||||
|
[hash.into(), user_id.into()],
|
||||||
|
))
|
||||||
|
.await?
|
||||||
|
.map(|result| result.try_get_by_index(0))
|
||||||
|
.transpose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use teloxide::{dispatching::DpHandlerDescription, dptree::Handler};
|
|
||||||
|
|
||||||
/// Deletes the message from the callback
|
/// Deletes the message from the callback
|
||||||
pub async fn delete_message(bot: Throttle<Bot>, q: CallbackQuery) -> crate::Result<()> {
|
pub async fn delete_message(bot: Throttle<Bot>, q: CallbackQuery) -> crate::Result<()> {
|
||||||
|
35
src/callbacks/get.rs
Normal file
35
src/callbacks/get.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use crate::prelude::*;
|
||||||
|
use teloxide::types::ParseMode;
|
||||||
|
|
||||||
|
pub async fn get(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
q: CallbackQuery,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
hash: super::NameHash,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let user_id = q.from.id.0;
|
||||||
|
let msg = q.message.as_ref().unwrap();
|
||||||
|
|
||||||
|
let hash = hex::encode(hash);
|
||||||
|
let name = match Account::get_name_by_hash(user_id, hash, &db).await? {
|
||||||
|
Some(name) => name,
|
||||||
|
None => {
|
||||||
|
bot.edit_message_text(
|
||||||
|
msg.chat.id,
|
||||||
|
msg.id,
|
||||||
|
"Account wan't found. Select another one",
|
||||||
|
)
|
||||||
|
.reply_markup(menu_markup(user_id, &db).await?)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let text = format!("Name:\n`{name}`\nLogin:\n***\nPassword:\n***");
|
||||||
|
bot.send_message(msg.chat.id, text)
|
||||||
|
.reply_markup(account_markup(&name, true))
|
||||||
|
.parse_mode(ParseMode::MarkdownV2)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -20,7 +20,7 @@ pub async fn get_menu(
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let markup = spawn_blocking(|| menu_markup(names)).await?;
|
let markup = spawn_blocking(|| menu_markup_sync(names)).await?;
|
||||||
bot.edit_message_text(msg.chat.id, msg.id, "Choose your account")
|
bot.edit_message_text(msg.chat.id, msg.id, "Choose your account")
|
||||||
.reply_markup(markup)
|
.reply_markup(markup)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -1,26 +1,28 @@
|
|||||||
//! This module consists of endpoints to handle callbacks
|
//! This module consists of endpoints to handle callbacks
|
||||||
|
|
||||||
mod delete_message;
|
mod delete_message;
|
||||||
|
mod get;
|
||||||
mod get_menu;
|
mod get_menu;
|
||||||
|
|
||||||
pub use delete_message::delete_message;
|
pub use delete_message::delete_message;
|
||||||
|
pub use get::get;
|
||||||
pub use get_menu::get_menu;
|
pub use get_menu::get_menu;
|
||||||
|
|
||||||
use crate::errors::InvalidCommand;
|
use crate::errors::InvalidCommand;
|
||||||
use base64::{engine::general_purpose::STANDARD_NO_PAD as B64_ENGINE, Engine as _};
|
use base64::{engine::general_purpose::STANDARD_NO_PAD as B64_ENGINE, Engine as _};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use teloxide::types::{CallbackQuery, Message};
|
use teloxide::types::CallbackQuery;
|
||||||
|
|
||||||
type NameHash = [u8; 32];
|
type NameHash = Vec<u8>;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum AlterableField {
|
pub enum AlterableField {
|
||||||
Name,
|
Name,
|
||||||
Login,
|
Login,
|
||||||
Pass,
|
Pass,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum CallbackCommand {
|
pub enum CallbackCommand {
|
||||||
DeleteMessage,
|
DeleteMessage,
|
||||||
Get(NameHash),
|
Get(NameHash),
|
||||||
@ -34,7 +36,7 @@ pub enum CallbackCommand {
|
|||||||
impl CallbackCommand {
|
impl CallbackCommand {
|
||||||
pub fn from_query(q: CallbackQuery) -> Option<Self> {
|
pub fn from_query(q: CallbackQuery) -> Option<Self> {
|
||||||
q.message.as_ref()?;
|
q.message.as_ref()?;
|
||||||
q.data.and_then(|text| text.parse().ok())
|
q.data.and_then(|text| dbg!(text.parse()).ok())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +47,8 @@ impl FromStr for CallbackCommand {
|
|||||||
use AlterableField::*;
|
use AlterableField::*;
|
||||||
use CallbackCommand::*;
|
use CallbackCommand::*;
|
||||||
|
|
||||||
|
println!("{s}");
|
||||||
|
|
||||||
match s {
|
match s {
|
||||||
"delete_message" => return Ok(DeleteMessage),
|
"delete_message" => return Ok(DeleteMessage),
|
||||||
"get_menu" => return Ok(GetMenu),
|
"get_menu" => return Ok(GetMenu),
|
||||||
@ -56,20 +60,19 @@ impl FromStr for CallbackCommand {
|
|||||||
(Some(command), Some(name), None) => (command, name),
|
(Some(command), Some(name), None) => (command, name),
|
||||||
_ => return Err(InvalidCommand::InvalidParams),
|
_ => return Err(InvalidCommand::InvalidParams),
|
||||||
};
|
};
|
||||||
|
let name_hash = B64_ENGINE.decode(name)?;
|
||||||
let mut name_arr = [0; 32];
|
if name_hash.len() != 32 {
|
||||||
if B64_ENGINE.decode_slice(name, &mut name_arr)? != 32 {
|
return Err(InvalidCommand::InvalidOutputLength);
|
||||||
return Err(InvalidCommand::OutputTooShort);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
match command {
|
match command {
|
||||||
"get" => Ok(Get(name_arr)),
|
"get" => Ok(Get(name_hash)),
|
||||||
"decrypt" => Ok(Decrypt(name_arr)),
|
"decrypt" => Ok(Decrypt(name_hash)),
|
||||||
"hide" => Ok(Hide(name_arr)),
|
"hide" => Ok(Hide(name_hash)),
|
||||||
"an" => Ok(Alter(name_arr, Name)),
|
"an" => Ok(Alter(name_hash, Name)),
|
||||||
"al" => Ok(Alter(name_arr, Login)),
|
"al" => Ok(Alter(name_hash, Login)),
|
||||||
"ap" => Ok(Alter(name_arr, Pass)),
|
"ap" => Ok(Alter(name_hash, Pass)),
|
||||||
"delete" => Ok(DeleteAccount(name_arr)),
|
"delete" => Ok(DeleteAccount(name_hash)),
|
||||||
_ => Err(InvalidCommand::InvalidParams),
|
_ => Err(InvalidCommand::InvalidParams),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,13 @@ async fn get_master_pass(
|
|||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
|
ids: MessageIds,
|
||||||
name: String,
|
name: String,
|
||||||
login: String,
|
login: String,
|
||||||
password: String,
|
password: String,
|
||||||
master_pass: String,
|
master_pass: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
ids.delete(&bot).await;
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
dialogue.exit().await?;
|
dialogue.exit().await?;
|
||||||
let account = spawn_blocking(move || {
|
let account = spawn_blocking(move || {
|
||||||
@ -38,4 +40,9 @@ handler!(get_login(name: String, login: String),
|
|||||||
get_password
|
get_password
|
||||||
);
|
);
|
||||||
handler!(get_account_name(name: String), "Send login", State::GetLogin, get_login);
|
handler!(get_account_name(name: String), "Send login", State::GetLogin, get_login);
|
||||||
handler!(pub add_account(), "Send account name", State::GetNewName, get_account_name);
|
first_handler!(
|
||||||
|
add_account,
|
||||||
|
"Send account name",
|
||||||
|
State::GetNewName,
|
||||||
|
get_account_name
|
||||||
|
);
|
||||||
|
@ -7,10 +7,13 @@ async fn get_master_pass(
|
|||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
|
ids: MessageIds,
|
||||||
name: String,
|
name: String,
|
||||||
_: String,
|
_: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
ids.delete(&bot).await;
|
||||||
dialogue.exit().await?;
|
dialogue.exit().await?;
|
||||||
|
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
Account::delete_by_id((user_id, name)).exec(&db).await?;
|
Account::delete_by_id((user_id, name)).exec(&db).await?;
|
||||||
bot.send_message(msg.chat.id, "The account is successfully deleted")
|
bot.send_message(msg.chat.id, "The account is successfully deleted")
|
||||||
@ -25,4 +28,8 @@ handler!(
|
|||||||
State::GetMasterPass,
|
State::GetMasterPass,
|
||||||
get_master_pass
|
get_master_pass
|
||||||
);
|
);
|
||||||
ask_name_handler!(pub delete(), "Send the name of the account to delete", get_account_name);
|
ask_name_handler!(
|
||||||
|
delete,
|
||||||
|
"Send the name of the account to delete",
|
||||||
|
get_account_name
|
||||||
|
);
|
||||||
|
@ -10,8 +10,10 @@ async fn get_master_pass(
|
|||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
|
ids: MessageIds,
|
||||||
_: String,
|
_: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
ids.delete(&bot).await;
|
||||||
dialogue.exit().await?;
|
dialogue.exit().await?;
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let txn = db.begin().await?;
|
let txn = db.begin().await?;
|
||||||
@ -36,8 +38,8 @@ async fn get_master_pass(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
handler!(
|
first_handler!(
|
||||||
pub delete_all(),
|
delete_all,
|
||||||
"Send master password to delete EVERYTHING.\nTHIS ACTION IS IRREVERSIBLE",
|
"Send master password to delete EVERYTHING.\nTHIS ACTION IS IRREVERSIBLE",
|
||||||
State::GetMasterPass,
|
State::GetMasterPass,
|
||||||
get_master_pass
|
get_master_pass
|
||||||
|
@ -23,8 +23,10 @@ async fn get_master_pass(
|
|||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
|
ids: MessageIds,
|
||||||
master_pass: String,
|
master_pass: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
ids.delete(&bot).await;
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let mut accounts = Vec::new();
|
let mut accounts = Vec::new();
|
||||||
|
|
||||||
@ -53,4 +55,9 @@ async fn get_master_pass(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
handler!(pub export(), "Send the master password to export your accounts", State::GetMasterPass, get_master_pass);
|
first_handler!(
|
||||||
|
export,
|
||||||
|
"Send the master password to export your accounts",
|
||||||
|
State::GetMasterPass,
|
||||||
|
get_master_pass
|
||||||
|
);
|
||||||
|
@ -8,10 +8,13 @@ async fn get_master_pass(
|
|||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
|
ids: MessageIds,
|
||||||
name: String,
|
name: String,
|
||||||
master_pass: String,
|
master_pass: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
ids.delete(&bot).await;
|
||||||
dialogue.exit().await?;
|
dialogue.exit().await?;
|
||||||
|
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let account = match Account::get(user_id, &name, &db).await? {
|
let account = match Account::get(user_id, &name, &db).await? {
|
||||||
Some(account) => account,
|
Some(account) => account,
|
||||||
@ -32,4 +35,8 @@ async fn get_master_pass(
|
|||||||
}
|
}
|
||||||
|
|
||||||
handler!(get_account_name(name:String), "Send master password", State::GetMasterPass, get_master_pass);
|
handler!(get_account_name(name:String), "Send master password", State::GetMasterPass, get_master_pass);
|
||||||
ask_name_handler!(pub get_account(), "Send the name of the account to get", get_account_name);
|
ask_name_handler!(
|
||||||
|
get_account,
|
||||||
|
"Send the name of the account to get",
|
||||||
|
get_account_name
|
||||||
|
);
|
||||||
|
@ -31,9 +31,11 @@ async fn get_master_pass(
|
|||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
|
ids: MessageIds,
|
||||||
user: User,
|
user: User,
|
||||||
master_pass: String,
|
master_pass: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
ids.delete(&bot).await;
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let mut failed = Vec::new();
|
let mut failed = Vec::new();
|
||||||
|
|
||||||
@ -64,4 +66,9 @@ async fn get_master_pass(
|
|||||||
}
|
}
|
||||||
|
|
||||||
handler!(get_user(user: User), "Send master password", State::GetMasterPass, get_master_pass);
|
handler!(get_user(user: User), "Send master password", State::GetMasterPass, get_master_pass);
|
||||||
handler!(pub import(), "Send a json document with the same format as created by /export", State::GetUser, get_user);
|
first_handler!(
|
||||||
|
import,
|
||||||
|
"Send a json document with the same format as created by /export",
|
||||||
|
State::GetUser,
|
||||||
|
get_user
|
||||||
|
);
|
||||||
|
@ -15,7 +15,7 @@ pub async fn menu(bot: Throttle<Bot>, msg: Message, db: DatabaseConnection) -> c
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let markup = spawn_blocking(|| menu_markup(names)).await?;
|
let markup = spawn_blocking(|| menu_markup_sync(names)).await?;
|
||||||
bot.send_message(msg.chat.id, "Choose your account")
|
bot.send_message(msg.chat.id, "Choose your account")
|
||||||
.reply_markup(markup)
|
.reply_markup(markup)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -7,9 +7,12 @@ async fn get_master_pass(
|
|||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
|
ids: MessageIds,
|
||||||
master_pass: String,
|
master_pass: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
ids.delete(&bot).await;
|
||||||
dialogue.exit().await?;
|
dialogue.exit().await?;
|
||||||
|
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let model =
|
let model =
|
||||||
spawn_blocking(move || master_pass::ActiveModel::from_unencrypted(user_id, &master_pass))
|
spawn_blocking(move || master_pass::ActiveModel::from_unencrypted(user_id, &master_pass))
|
||||||
@ -40,10 +43,10 @@ pub async fn set_master_pass(
|
|||||||
.await?;
|
.await?;
|
||||||
dialogue
|
dialogue
|
||||||
.update(State::GetNewMasterPass(Handler::new(
|
.update(State::GetNewMasterPass(Handler::new(
|
||||||
|bot, msg, db, dialogue, master_pass| {
|
|bot, msg, db, dialogue, ids, master_pass| {
|
||||||
Box::pin(get_master_pass(bot, msg, db, dialogue, master_pass))
|
Box::pin(get_master_pass(bot, msg, db, dialogue, ids, master_pass))
|
||||||
},
|
},
|
||||||
&previous,
|
MessageIds::from(&previous),
|
||||||
)))
|
)))
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -11,7 +11,7 @@ pub enum InvalidCommand {
|
|||||||
#[error("Invalid params")]
|
#[error("Invalid params")]
|
||||||
InvalidParams,
|
InvalidParams,
|
||||||
#[error("Not enough bytes in the name's hash")]
|
#[error("Not enough bytes in the name's hash")]
|
||||||
OutputTooShort,
|
InvalidOutputLength,
|
||||||
#[error("Error decoding the values: {0}")]
|
#[error("Error decoding the values: {0}")]
|
||||||
NameDecodingError(#[from] base64::DecodeSliceError),
|
NameDecodingError(#[from] base64::DecodeError),
|
||||||
}
|
}
|
||||||
|
@ -1,39 +1,66 @@
|
|||||||
|
#[macro_export]
|
||||||
|
macro_rules! change_state {
|
||||||
|
($dialogue: expr, $previous: expr, ($($param: ident),*), $message: literal, $next_state: expr, $next_func: ident) => {{
|
||||||
|
$dialogue
|
||||||
|
.update($next_state(Handler::new(
|
||||||
|
move |bot, msg, db, dialogue, ids, param| Box::pin($next_func(bot, msg, db, dialogue, ids, $($param,)* param)),
|
||||||
|
&$previous,
|
||||||
|
)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! first_handler {
|
||||||
|
($function_name: ident, $message: expr, $next_state: expr, $next_func: ident) => {
|
||||||
|
#[inline]
|
||||||
|
pub async fn $function_name(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
) -> $crate::Result<()> {
|
||||||
|
let previous = bot.send_message(msg.chat.id, $message).await?;
|
||||||
|
|
||||||
|
$crate::change_state!(dialogue, previous, (), $message, $next_state, $next_func)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! handler {
|
macro_rules! handler {
|
||||||
($v: vis $function_name: ident ($($param: ident: $type: ty),*), $message: literal, $next_state: expr, $next_func: ident) => {
|
($function_name: ident ($($param: ident: $type: ty),*), $message: literal, $next_state: expr, $next_func: ident) => {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[inline]
|
#[inline]
|
||||||
$v async fn $function_name(
|
async fn $function_name(
|
||||||
bot: Throttle<Bot>,
|
bot: Throttle<Bot>,
|
||||||
msg: Message,
|
msg: Message,
|
||||||
_: DatabaseConnection,
|
_: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
|
ids: MessageIds,
|
||||||
$($param: $type),*
|
$($param: $type),*
|
||||||
) -> $crate::Result<()> {
|
) -> $crate::Result<()> {
|
||||||
|
ids.delete(&bot).await;
|
||||||
|
|
||||||
let previous = bot.send_message(msg.chat.id, $message).await?;
|
let previous = bot.send_message(msg.chat.id, $message).await?;
|
||||||
dialogue
|
|
||||||
.update($next_state(Handler::new(
|
$crate::change_state!(dialogue, previous, ($($param),*), $message, $next_state, $next_func)
|
||||||
move |bot, msg, db, dialogue, param| Box::pin($next_func(bot, msg, db, dialogue, $($param,)* param)),
|
|
||||||
&previous,
|
|
||||||
)))
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! ask_name_handler {
|
macro_rules! ask_name_handler {
|
||||||
($v: vis $function_name: ident ($($param: ident: $type: ty),*), $message: literal, $next_func: ident) => {
|
($function_name: ident, $message: literal, $next_func: ident) => {
|
||||||
#[inline]
|
#[inline]
|
||||||
$v async fn $function_name(
|
pub async fn $function_name(
|
||||||
bot: Throttle<Bot>,
|
bot: Throttle<Bot>,
|
||||||
msg: Message,
|
msg: Message,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
$($param: $type),*
|
|
||||||
) -> $crate::Result<()> {
|
) -> $crate::Result<()> {
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let markup = account_markup(user_id, &db).await?;
|
let markup = account_list_markup(user_id, &db).await?;
|
||||||
if markup.keyboard.is_empty() {
|
if markup.keyboard.is_empty() {
|
||||||
bot.send_message(msg.chat.id, "No accounts found")
|
bot.send_message(msg.chat.id, "No accounts found")
|
||||||
.reply_markup(deletion_markup())
|
.reply_markup(deletion_markup())
|
||||||
@ -44,13 +71,15 @@ macro_rules! ask_name_handler {
|
|||||||
.send_message(msg.chat.id, $message)
|
.send_message(msg.chat.id, $message)
|
||||||
.reply_markup(markup)
|
.reply_markup(markup)
|
||||||
.await?;
|
.await?;
|
||||||
dialogue
|
|
||||||
.update(State::GetExistingName(Handler::new(
|
$crate::change_state!(
|
||||||
move |bot, msg, db, dialogue, param| Box::pin($next_func(bot, msg, db, dialogue, $($param,)* param)),
|
dialogue,
|
||||||
&previous,
|
previous,
|
||||||
)))
|
(),
|
||||||
.await?;
|
$message,
|
||||||
Ok(())
|
State::GetExistingName,
|
||||||
|
$next_func
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -71,7 +100,7 @@ macro_rules! simple_state_handler {
|
|||||||
msg,
|
msg,
|
||||||
db,
|
db,
|
||||||
dialogue,
|
dialogue,
|
||||||
|bot, msg, db, param| Box::pin($check(bot, msg, db, param)),
|
|msg, db, param| Box::pin($check(msg, db, param)),
|
||||||
$no_text_message,
|
$no_text_message,
|
||||||
next,
|
next,
|
||||||
)
|
)
|
||||||
|
@ -63,7 +63,8 @@ fn get_dispatcher(
|
|||||||
let callback_handler = Update::filter_callback_query()
|
let callback_handler = Update::filter_callback_query()
|
||||||
.filter_map(CallbackCommand::from_query)
|
.filter_map(CallbackCommand::from_query)
|
||||||
.branch(case![CallbackCommand::GetMenu].endpoint(callbacks::get_menu))
|
.branch(case![CallbackCommand::GetMenu].endpoint(callbacks::get_menu))
|
||||||
.branch(case![CallbackCommand::DeleteMessage].endpoint(callbacks::delete_message));
|
.branch(case![CallbackCommand::DeleteMessage].endpoint(callbacks::delete_message))
|
||||||
|
.branch(case![CallbackCommand::Get(hash)].endpoint(callbacks::get));
|
||||||
|
|
||||||
let handler = dptree::entry()
|
let handler = dptree::entry()
|
||||||
.branch(message_handler)
|
.branch(message_handler)
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use base64::{engine::general_purpose::STANDARD as B64_ENGINE, Engine as _};
|
use base64::{engine::general_purpose::STANDARD_NO_PAD as B64_ENGINE, Engine as _};
|
||||||
use futures::future;
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, KeyboardMarkup};
|
use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup, KeyboardButton, KeyboardMarkup};
|
||||||
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
/// Creates a markup of all user's account names
|
/// Creates a markup of all user's account names
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn account_markup(
|
pub async fn account_list_markup(
|
||||||
user_id: u64,
|
user_id: u64,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> crate::Result<KeyboardMarkup> {
|
) -> crate::Result<KeyboardMarkup> {
|
||||||
@ -25,7 +25,7 @@ pub async fn account_markup(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn menu_markup(names: impl IntoIterator<Item = String>) -> InlineKeyboardMarkup {
|
pub fn menu_markup_sync(names: impl IntoIterator<Item = String>) -> InlineKeyboardMarkup {
|
||||||
let names = names
|
let names = names
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|name| {
|
.map(|name| {
|
||||||
@ -40,6 +40,57 @@ pub fn menu_markup(names: impl IntoIterator<Item = String>) -> InlineKeyboardMar
|
|||||||
InlineKeyboardMarkup::new(&names)
|
InlineKeyboardMarkup::new(&names)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub async fn menu_markup(
|
||||||
|
user_id: u64,
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
) -> crate::Result<InlineKeyboardMarkup> {
|
||||||
|
let names: Vec<String> = Account::get_names(user_id, db).await?.try_collect().await?;
|
||||||
|
|
||||||
|
spawn_blocking(|| menu_markup_sync(names))
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn make_button(text: &str, command: &str, hash: &str) -> InlineKeyboardButton {
|
||||||
|
let mut data = command.to_owned();
|
||||||
|
data.reserve(44);
|
||||||
|
data.push(' ');
|
||||||
|
data.push_str(hash);
|
||||||
|
InlineKeyboardButton::callback(text, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn account_markup(name: &str, is_encrypted: bool) -> InlineKeyboardMarkup {
|
||||||
|
let mut hash = [0; 43];
|
||||||
|
B64_ENGINE
|
||||||
|
.encode_slice(<Sha256 as Digest>::digest(name), &mut hash)
|
||||||
|
.unwrap();
|
||||||
|
let hash = std::str::from_utf8(&hash).unwrap();
|
||||||
|
|
||||||
|
let alter_buttons = [
|
||||||
|
("Alter name", "an"),
|
||||||
|
("Alter login", "al"),
|
||||||
|
("Alter password", "ap"),
|
||||||
|
]
|
||||||
|
.map(|(text, command)| make_button(text, command, hash));
|
||||||
|
|
||||||
|
let mut second_raw = Vec::new();
|
||||||
|
if is_encrypted {
|
||||||
|
second_raw.push(make_button("Decrypt", "decrypt", hash))
|
||||||
|
} else {
|
||||||
|
second_raw.push(make_button("Hide", "hide", hash));
|
||||||
|
}
|
||||||
|
second_raw.push(make_button("Delete account", "delete", hash));
|
||||||
|
|
||||||
|
let menu_button = InlineKeyboardButton::callback("Back to the menu", "get_menu");
|
||||||
|
|
||||||
|
InlineKeyboardMarkup::new([alter_buttons])
|
||||||
|
.append_row(second_raw)
|
||||||
|
.append_row([menu_button])
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a markup with a "Delete message" button.
|
/// Creates a markup with a "Delete message" button.
|
||||||
/// This markup should be added for all messages that won't be deleted afterwards
|
/// This markup should be added for all messages that won't be deleted afterwards
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -2,7 +2,7 @@ pub(crate) use crate::{
|
|||||||
ask_name_handler,
|
ask_name_handler,
|
||||||
commands::Command,
|
commands::Command,
|
||||||
errors::*,
|
errors::*,
|
||||||
handler,
|
first_handler, handler,
|
||||||
markups::*,
|
markups::*,
|
||||||
models::*,
|
models::*,
|
||||||
state::State,
|
state::State,
|
||||||
|
@ -14,11 +14,10 @@ pub async fn generic<F>(
|
|||||||
) -> crate::Result<()>
|
) -> crate::Result<()>
|
||||||
where
|
where
|
||||||
for<'a> F: FnOnce(
|
for<'a> F: FnOnce(
|
||||||
&'a Throttle<Bot>,
|
|
||||||
&'a Message,
|
&'a Message,
|
||||||
&'a DatabaseConnection,
|
&'a DatabaseConnection,
|
||||||
&'a str,
|
&'a str,
|
||||||
) -> BoxFuture<'a, crate::Result<Option<Message>>>,
|
) -> BoxFuture<'a, crate::Result<Option<String>>>,
|
||||||
{
|
{
|
||||||
let mut handler = next.lock().await;
|
let mut handler = next.lock().await;
|
||||||
if handler.func.is_none() {
|
if handler.func.is_none() {
|
||||||
@ -26,8 +25,6 @@ where
|
|||||||
return Err(HandlerUsed.into());
|
return Err(HandlerUsed.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.previous.delete(&bot).await;
|
|
||||||
|
|
||||||
let text = match msg.text() {
|
let text = match msg.text() {
|
||||||
Some(text) => text.trim(),
|
Some(text) => text.trim(),
|
||||||
None => {
|
None => {
|
||||||
@ -45,16 +42,18 @@ where
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(failure_message) = check(&bot, &msg, &db, text).await? {
|
if let Some(text) = check(&msg, &db, text).await? {
|
||||||
|
let failure_message = bot.send_message(msg.chat.id, text).await?;
|
||||||
handler.previous = MessageIds::from(&failure_message);
|
handler.previous = MessageIds::from(&failure_message);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let previous = handler.previous;
|
||||||
let func = handler.func.take().unwrap();
|
let func = handler.func.take().unwrap();
|
||||||
drop(handler);
|
drop(handler);
|
||||||
let text = text.to_owned();
|
let text = text.to_owned();
|
||||||
|
|
||||||
if let Err(err) = func(bot, msg, db, dialogue.clone(), text).await {
|
if let Err(err) = func(bot, msg, db, dialogue.clone(), previous, text).await {
|
||||||
let _ = dialogue.exit().await;
|
let _ = dialogue.exit().await;
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,5 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// Checks that the account with that name exists
|
|
||||||
#[inline]
|
|
||||||
async fn check_name(
|
|
||||||
bot: &Throttle<Bot>,
|
|
||||||
msg: &Message,
|
|
||||||
db: &DatabaseConnection,
|
|
||||||
name: &str,
|
|
||||||
user_id: u64,
|
|
||||||
) -> crate::Result<Option<Message>> {
|
|
||||||
if !Account::exists(user_id, name, db).await? {
|
|
||||||
let msg = bot
|
|
||||||
.send_message(msg.chat.id, "Account doesn't exists. Try again")
|
|
||||||
.reply_markup(account_markup(user_id, db).await?)
|
|
||||||
.await?;
|
|
||||||
return Ok(Some(msg));
|
|
||||||
}
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Function to handle GetExistingName state
|
/// Function to handle GetExistingName state
|
||||||
pub async fn get_existing_name(
|
pub async fn get_existing_name(
|
||||||
bot: Throttle<Bot>,
|
bot: Throttle<Bot>,
|
||||||
@ -35,8 +16,6 @@ pub async fn get_existing_name(
|
|||||||
return Err(HandlerUsed.into());
|
return Err(HandlerUsed.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.previous.delete(&bot).await;
|
|
||||||
|
|
||||||
let text = match msg.text() {
|
let text = match msg.text() {
|
||||||
Some(text) => text.trim(),
|
Some(text) => text.trim(),
|
||||||
None => {
|
None => {
|
||||||
@ -45,7 +24,7 @@ pub async fn get_existing_name(
|
|||||||
msg.chat.id,
|
msg.chat.id,
|
||||||
"Couldn't get the text of the message. Send the name again",
|
"Couldn't get the text of the message. Send the name again",
|
||||||
)
|
)
|
||||||
.reply_markup(account_markup(user_id, &db).await?)
|
.reply_markup(account_list_markup(user_id, &db).await?)
|
||||||
.await?;
|
.await?;
|
||||||
handler.previous = MessageIds::from(&msg);
|
handler.previous = MessageIds::from(&msg);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -60,16 +39,21 @@ pub async fn get_existing_name(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(failure_message) = check_name(&bot, &msg, &db, text, user_id).await? {
|
if !Account::exists(user_id, text, &db).await? {
|
||||||
handler.previous = MessageIds::from(&failure_message);
|
let msg = bot
|
||||||
|
.send_message(msg.chat.id, "Account doesn't exists. Try again")
|
||||||
|
.reply_markup(account_list_markup(user_id, &db).await?)
|
||||||
|
.await?;
|
||||||
|
handler.previous = MessageIds::from(&msg);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let previous = handler.previous;
|
||||||
let func = handler.func.take().unwrap();
|
let func = handler.func.take().unwrap();
|
||||||
drop(handler);
|
drop(handler);
|
||||||
let text = text.to_owned();
|
let text = text.to_owned();
|
||||||
|
|
||||||
if let Err(err) = func(bot, msg, db, dialogue.clone(), text).await {
|
if let Err(err) = func(bot, msg, db, dialogue.clone(), previous, text).await {
|
||||||
let _ = dialogue.exit().await;
|
let _ = dialogue.exit().await;
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,13 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
async fn check_login(
|
async fn check_login(
|
||||||
bot: &Throttle<Bot>,
|
_: &Message,
|
||||||
msg: &Message,
|
|
||||||
_: &DatabaseConnection,
|
_: &DatabaseConnection,
|
||||||
login: &str,
|
login: &str,
|
||||||
) -> crate::Result<Option<Message>> {
|
) -> crate::Result<Option<String>> {
|
||||||
let is_valid = validate_field(login);
|
let is_valid = validate_field(login);
|
||||||
if !is_valid {
|
if !is_valid {
|
||||||
let msg = bot
|
return Ok(Some("Invalid login. Try again".to_owned()));
|
||||||
.send_message(msg.chat.id, "Invalid login. Try again")
|
|
||||||
.await?;
|
|
||||||
return Ok(Some(msg));
|
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,10 @@ use tokio::task::spawn_blocking;
|
|||||||
/// Returns true if the provided master password is valid
|
/// Returns true if the provided master password is valid
|
||||||
#[inline]
|
#[inline]
|
||||||
async fn check_master_pass(
|
async fn check_master_pass(
|
||||||
bot: &Throttle<Bot>,
|
|
||||||
msg: &Message,
|
msg: &Message,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
master_pass: &str,
|
master_pass: &str,
|
||||||
) -> crate::Result<Option<Message>> {
|
) -> crate::Result<Option<String>> {
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let model = MasterPass::get(user_id, db).await?;
|
let model = MasterPass::get(user_id, db).await?;
|
||||||
|
|
||||||
@ -20,21 +19,15 @@ async fn check_master_pass(
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
error!("User was put into the GetMasterPass state with no master password set");
|
error!("User was put into the GetMasterPass state with no master password set");
|
||||||
let msg = bot
|
return Ok(Some(
|
||||||
.send_message(
|
"No master password set. Use /cancel and set it by using /set_master_pass"
|
||||||
msg.chat.id,
|
.to_owned(),
|
||||||
"No master password set. Use /cancel and set it by using /set_master_pass",
|
));
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
return Ok(Some(msg));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !is_valid {
|
if !is_valid {
|
||||||
let msg = bot
|
return Ok(Some("Wrong master password. Try again".to_owned()));
|
||||||
.send_message(msg.chat.id, "Wrong master password. Try again")
|
|
||||||
.await?;
|
|
||||||
return Ok(Some(msg));
|
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -33,20 +33,13 @@ fn process_validity(validity: PasswordValidity) -> Result<(), String> {
|
|||||||
/// Checks that the account with that name exists
|
/// Checks that the account with that name exists
|
||||||
#[inline]
|
#[inline]
|
||||||
async fn check_new_master_pass(
|
async fn check_new_master_pass(
|
||||||
bot: &Throttle<Bot>,
|
_: &Message,
|
||||||
msg: &Message,
|
|
||||||
_: &DatabaseConnection,
|
_: &DatabaseConnection,
|
||||||
password: &str,
|
password: &str,
|
||||||
) -> crate::Result<Option<Message>> {
|
) -> crate::Result<Option<String>> {
|
||||||
let validity = check_master_pass(password);
|
let validity = check_master_pass(password);
|
||||||
|
|
||||||
match process_validity(validity) {
|
Ok(process_validity(validity).err())
|
||||||
Ok(()) => Ok(None),
|
|
||||||
Err(error_text) => {
|
|
||||||
let msg = bot.send_message(msg.chat.id, error_text).await?;
|
|
||||||
Ok(Some(msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::simple_state_handler!(
|
crate::simple_state_handler!(
|
||||||
|
@ -3,26 +3,19 @@ use crate::prelude::*;
|
|||||||
/// Validates a new account
|
/// Validates a new account
|
||||||
#[inline]
|
#[inline]
|
||||||
async fn check_new_account_name(
|
async fn check_new_account_name(
|
||||||
bot: &Throttle<Bot>,
|
|
||||||
msg: &Message,
|
msg: &Message,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> crate::Result<Option<Message>> {
|
) -> crate::Result<Option<String>> {
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
if Account::exists(user_id, name, db).await? {
|
|
||||||
let msg = bot
|
|
||||||
.send_message(msg.chat.id, "Account already exists")
|
|
||||||
.await?;
|
|
||||||
return Ok(Some(msg));
|
|
||||||
}
|
|
||||||
if !validate_field(name) {
|
|
||||||
let msg = bot
|
|
||||||
.send_message(msg.chat.id, "Invalid account name. Try again")
|
|
||||||
.await?;
|
|
||||||
return Ok(Some(msg));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
if Account::exists(user_id, name, db).await? {
|
||||||
|
Ok(Some("Account already exists".to_owned()))
|
||||||
|
} else if !validate_field(name) {
|
||||||
|
Ok(Some("Invalid account name. Try again".to_owned()))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate::simple_state_handler!(
|
crate::simple_state_handler!(
|
||||||
|
@ -2,17 +2,13 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
async fn check_password(
|
async fn check_password(
|
||||||
bot: &Throttle<Bot>,
|
_: &Message,
|
||||||
msg: &Message,
|
|
||||||
_: &DatabaseConnection,
|
_: &DatabaseConnection,
|
||||||
login: &str,
|
password: &str,
|
||||||
) -> crate::Result<Option<Message>> {
|
) -> crate::Result<Option<String>> {
|
||||||
let is_valid = validate_field(login);
|
let is_valid = validate_field(password);
|
||||||
if !is_valid {
|
if !is_valid {
|
||||||
let msg = bot
|
return Ok(Some("Invalid password. Try again".to_owned()));
|
||||||
.send_message(msg.chat.id, "Invalid password. Try again")
|
|
||||||
.await?;
|
|
||||||
return Ok(Some(msg));
|
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -145,8 +145,6 @@ pub async fn get_user(
|
|||||||
return Err(HandlerUsed.into());
|
return Err(HandlerUsed.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.previous.delete(&bot).await;
|
|
||||||
|
|
||||||
if let Some("/cancel") = msg.text().map(str::trim) {
|
if let Some("/cancel") = msg.text().map(str::trim) {
|
||||||
dialogue.exit().await?;
|
dialogue.exit().await?;
|
||||||
bot.send_message(msg.chat.id, "Successfully cancelled")
|
bot.send_message(msg.chat.id, "Successfully cancelled")
|
||||||
@ -190,10 +188,11 @@ pub async fn get_user(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let previous = handler.previous;
|
||||||
let func = handler.func.take().unwrap();
|
let func = handler.func.take().unwrap();
|
||||||
drop(handler);
|
drop(handler);
|
||||||
|
|
||||||
if let Err(err) = func(bot, msg, db, dialogue.clone(), user).await {
|
if let Err(err) = func(bot, msg, db, dialogue.clone(), previous, user).await {
|
||||||
let _ = dialogue.exit().await;
|
let _ = dialogue.exit().await;
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use teloxide::types::MessageId;
|
use teloxide::types::{InlineKeyboardMarkup, MessageId};
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -27,6 +27,7 @@ type DynHanlder<T> = Box<
|
|||||||
Message,
|
Message,
|
||||||
DatabaseConnection,
|
DatabaseConnection,
|
||||||
MainDialogue,
|
MainDialogue,
|
||||||
|
MessageIds,
|
||||||
T,
|
T,
|
||||||
) -> BoxFuture<'static, crate::Result<()>>
|
) -> BoxFuture<'static, crate::Result<()>>
|
||||||
+ Send,
|
+ Send,
|
||||||
@ -50,6 +51,7 @@ impl<T> Handler<T> {
|
|||||||
Message,
|
Message,
|
||||||
DatabaseConnection,
|
DatabaseConnection,
|
||||||
MainDialogue,
|
MainDialogue,
|
||||||
|
MessageIds,
|
||||||
T,
|
T,
|
||||||
) -> BoxFuture<'static, crate::Result<()>>
|
) -> BoxFuture<'static, crate::Result<()>>
|
||||||
+ Send
|
+ Send
|
||||||
|
Loading…
x
Reference in New Issue
Block a user