added get endpoint, updated state_management
This commit is contained in:
		@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user