Switched to inline buttons when getting the account name, finished decrypt and delete Callback commands
This commit is contained in:
parent
5c14a77f29
commit
0139963459
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -1666,7 +1666,7 @@ checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata 0.3.3",
|
"regex-automata 0.3.4",
|
||||||
"regex-syntax 0.7.4",
|
"regex-syntax 0.7.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1681,9 +1681,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -2118,18 +2118,18 @@ checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.177"
|
version = "1.0.178"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "63ba2516aa6bf82e0b19ca8b50019d52df58455d3cf9bdaf6315225fdd0c560a"
|
checksum = "60363bdd39a7be0266a520dab25fdc9241d2f987b08a01e01f0ec6d06a981348"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.177"
|
version = "1.0.178"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "401797fe7833d72109fedec6bfcbe67c0eed9b99772f26eb8afd261f0abc6fd3"
|
checksum = "f28482318d6641454cb273da158647922d1be6b5a2fcc6165cd89ebdd7ed576b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
68
src/callbacks/decrypt.rs
Normal file
68
src/callbacks/decrypt.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use crate::{change_state, prelude::*};
|
||||||
|
use teloxide::types::ParseMode;
|
||||||
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
|
async fn get_master_pass(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
mut ids: MessageIds,
|
||||||
|
name: String,
|
||||||
|
master_pass: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
dialogue.exit().await?;
|
||||||
|
|
||||||
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
|
|
||||||
|
let account = match Account::get(user_id, &name, &db).await? {
|
||||||
|
Some(account) => account,
|
||||||
|
None => {
|
||||||
|
bot.send_message(msg.chat.id, "Account not found")
|
||||||
|
.reply_markup(deletion_markup())
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let (login, password) = spawn_blocking(move || account.decrypt(&master_pass)).await??;
|
||||||
|
let text = format!("Name:\n`{name}`\nLogin:\n`{login}`\nPassword:\n`{password}`");
|
||||||
|
|
||||||
|
ids.alter_message(
|
||||||
|
&bot,
|
||||||
|
text,
|
||||||
|
account_markup(&name, false),
|
||||||
|
ParseMode::MarkdownV2,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn decrypt(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
q: CallbackQuery,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
hash: super::NameHash,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let mut msg: MessageIds = q.message.as_ref().unwrap().into();
|
||||||
|
let user_id = q.from.id.0;
|
||||||
|
let name = match name_from_hash(&db, user_id, &hash).await? {
|
||||||
|
Some(name) => name,
|
||||||
|
None => {
|
||||||
|
msg.alter_message(
|
||||||
|
&bot,
|
||||||
|
"Account wan't found. Select another one",
|
||||||
|
menu_markup("decrypt", user_id, &db).await?,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
msg.alter_message(&bot, "Send master password", None, None)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
change_state!(dialogue, msg, (name), State::GetMasterPass, get_master_pass)
|
||||||
|
}
|
63
src/callbacks/delete.rs
Normal file
63
src/callbacks/delete.rs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
use crate::{change_state, prelude::*};
|
||||||
|
|
||||||
|
async fn get_master_pass(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
mut ids: MessageIds,
|
||||||
|
name: String,
|
||||||
|
_: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
dialogue.exit().await?;
|
||||||
|
|
||||||
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
|
Account::delete_by_id((user_id, name)).exec(&db).await?;
|
||||||
|
|
||||||
|
ids.alter_message(
|
||||||
|
&bot,
|
||||||
|
"The account is successfully deleted",
|
||||||
|
deletion_markup(),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
q: CallbackQuery,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
hash: super::NameHash,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let mut msg: MessageIds = q.message.as_ref().unwrap().into();
|
||||||
|
let user_id = q.from.id.0;
|
||||||
|
let name = match name_from_hash(&db, user_id, &hash).await? {
|
||||||
|
Some(name) => name,
|
||||||
|
None => {
|
||||||
|
msg.alter_message(
|
||||||
|
&bot,
|
||||||
|
"Account wan't found. Select another one",
|
||||||
|
menu_markup("delete", user_id, &db).await?,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let previous = bot.send_message(
|
||||||
|
msg.0,
|
||||||
|
"Send master password. Once you send correct master password the account is unrecoverable"
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
change_state!(
|
||||||
|
dialogue,
|
||||||
|
&previous,
|
||||||
|
(name),
|
||||||
|
State::GetMasterPass,
|
||||||
|
get_master_pass
|
||||||
|
)
|
||||||
|
}
|
@ -10,8 +10,7 @@ pub async fn get(
|
|||||||
let user_id = q.from.id.0;
|
let user_id = q.from.id.0;
|
||||||
let msg = q.message.as_ref().unwrap();
|
let msg = q.message.as_ref().unwrap();
|
||||||
|
|
||||||
let hash = hex::encode(hash);
|
let name = match name_from_hash(&db, user_id, &hash).await? {
|
||||||
let name = match Account::get_name_by_hash(user_id, hash, &db).await? {
|
|
||||||
Some(name) => name,
|
Some(name) => name,
|
||||||
None => {
|
None => {
|
||||||
bot.edit_message_text(
|
bot.edit_message_text(
|
||||||
@ -19,13 +18,13 @@ pub async fn get(
|
|||||||
msg.id,
|
msg.id,
|
||||||
"Account wan't found. Select another one",
|
"Account wan't found. Select another one",
|
||||||
)
|
)
|
||||||
.reply_markup(menu_markup(user_id, &db).await?)
|
.reply_markup(menu_markup("get", user_id, &db).await?)
|
||||||
.await?;
|
.await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let text = format!("Name:\n`{name}`\nLogin:\n***\nPassword:\n***");
|
let text = format!("Name:\n`{name}`\nLogin:\n\\*\\*\\*\nPassword:\n\\*\\*\\*");
|
||||||
bot.send_message(msg.chat.id, text)
|
bot.send_message(msg.chat.id, text)
|
||||||
.reply_markup(account_markup(&name, true))
|
.reply_markup(account_markup(&name, true))
|
||||||
.parse_mode(ParseMode::MarkdownV2)
|
.parse_mode(ParseMode::MarkdownV2)
|
||||||
|
@ -18,9 +18,10 @@ pub async fn get_menu(
|
|||||||
bot.edit_message_text(msg.chat.id, msg.id, "You don't have any accounts")
|
bot.edit_message_text(msg.chat.id, msg.id, "You don't have any accounts")
|
||||||
.reply_markup(deletion_markup())
|
.reply_markup(deletion_markup())
|
||||||
.await?;
|
.await?;
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let markup = spawn_blocking(|| menu_markup_sync(names)).await?;
|
let markup = spawn_blocking(|| menu_markup_sync("get", 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,9 +1,13 @@
|
|||||||
//! This module consists of endpoints to handle callbacks
|
//! This module consists of endpoints to handle callbacks
|
||||||
|
|
||||||
|
mod decrypt;
|
||||||
|
mod delete;
|
||||||
mod delete_message;
|
mod delete_message;
|
||||||
mod get;
|
mod get;
|
||||||
mod get_menu;
|
mod get_menu;
|
||||||
|
|
||||||
|
pub use decrypt::decrypt;
|
||||||
|
pub use delete::delete;
|
||||||
pub use delete_message::delete_message;
|
pub use delete_message::delete_message;
|
||||||
pub use get::get;
|
pub use get::get;
|
||||||
pub use get_menu::get_menu;
|
pub use get_menu::get_menu;
|
||||||
@ -36,7 +40,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| dbg!(text.parse()).ok())
|
q.data.and_then(|data| data.parse().ok())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +51,6 @@ 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),
|
||||||
|
@ -1,40 +1,11 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/// Gets the master password and deletes the account.
|
pub async fn delete(bot: Throttle<Bot>, msg: Message, db: DatabaseConnection) -> crate::Result<()> {
|
||||||
/// Although it doesn't use the master password, we get it to be sure that it's the user who used that command
|
|
||||||
async fn get_master_pass(
|
|
||||||
bot: Throttle<Bot>,
|
|
||||||
msg: Message,
|
|
||||||
db: DatabaseConnection,
|
|
||||||
dialogue: MainDialogue,
|
|
||||||
mut ids: MessageIds,
|
|
||||||
name: String,
|
|
||||||
_: String,
|
|
||||||
) -> crate::Result<()> {
|
|
||||||
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?;
|
|
||||||
|
|
||||||
ids.alter_message(
|
bot.send_message(msg.chat.id, "Choose the account to delete")
|
||||||
&bot,
|
.reply_markup(menu_markup("delete", user_id, &db).await?)
|
||||||
"The account is successfully deleted",
|
.await?;
|
||||||
deletion_markup(),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
handler!(
|
|
||||||
get_account_name(name: String),
|
|
||||||
"Send master password. Once you send correct master password the account is unrecoverable",
|
|
||||||
State::GetMasterPass,
|
|
||||||
get_master_pass
|
|
||||||
);
|
|
||||||
ask_name_handler!(
|
|
||||||
delete,
|
|
||||||
"Send the name of the account to delete",
|
|
||||||
get_account_name
|
|
||||||
);
|
|
||||||
|
@ -1,42 +1,15 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use teloxide::types::ParseMode;
|
|
||||||
use tokio::task::spawn_blocking;
|
|
||||||
|
|
||||||
/// Gets the master password, decryptes the account and sends it to the user with copyable fields
|
pub async fn get_account(
|
||||||
async fn get_master_pass(
|
|
||||||
bot: Throttle<Bot>,
|
bot: Throttle<Bot>,
|
||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
|
||||||
mut ids: MessageIds,
|
|
||||||
name: String,
|
|
||||||
master_pass: String,
|
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
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? {
|
bot.send_message(msg.chat.id, "Choose the account to get")
|
||||||
Some(account) => account,
|
.reply_markup(menu_markup("decrypt", user_id, &db).await?)
|
||||||
None => {
|
|
||||||
bot.send_message(msg.chat.id, "Account not found")
|
|
||||||
.reply_markup(deletion_markup())
|
|
||||||
.await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (login, password) = spawn_blocking(move || account.decrypt(&master_pass)).await??;
|
|
||||||
let text = format!("Name:\n`{name}`\nLogin:\n`{login}`\nPassword:\n`{password}`");
|
|
||||||
|
|
||||||
ids.alter_message(&bot, text, deletion_markup(), ParseMode::MarkdownV2)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
handler!(get_account_name(name:String), "Send master password", State::GetMasterPass, get_master_pass);
|
|
||||||
ask_name_handler!(
|
|
||||||
get_account,
|
|
||||||
"Send the name of the account to get",
|
|
||||||
get_account_name
|
|
||||||
);
|
|
||||||
|
@ -15,7 +15,7 @@ pub async fn menu(bot: Throttle<Bot>, msg: Message, db: DatabaseConnection) -> c
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let markup = spawn_blocking(|| menu_markup_sync(names)).await?;
|
let markup = spawn_blocking(|| menu_markup_sync("get", 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?;
|
||||||
|
@ -34,7 +34,7 @@ macro_rules! handler {
|
|||||||
#[inline]
|
#[inline]
|
||||||
async fn $function_name(
|
async fn $function_name(
|
||||||
bot: Throttle<Bot>,
|
bot: Throttle<Bot>,
|
||||||
msg: Message,
|
_: Message,
|
||||||
_: DatabaseConnection,
|
_: DatabaseConnection,
|
||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
mut ids: MessageIds,
|
mut ids: MessageIds,
|
||||||
@ -47,34 +47,6 @@ macro_rules! handler {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! ask_name_handler {
|
|
||||||
($function_name: ident, $message: literal, $next_func: ident) => {
|
|
||||||
#[inline]
|
|
||||||
pub async fn $function_name(
|
|
||||||
bot: Throttle<Bot>,
|
|
||||||
msg: Message,
|
|
||||||
dialogue: MainDialogue,
|
|
||||||
db: DatabaseConnection,
|
|
||||||
) -> $crate::Result<()> {
|
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
|
||||||
let markup = account_list_markup(user_id, &db).await?;
|
|
||||||
if markup.keyboard.is_empty() {
|
|
||||||
bot.send_message(msg.chat.id, "No accounts found")
|
|
||||||
.reply_markup(deletion_markup())
|
|
||||||
.await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let previous = bot
|
|
||||||
.send_message(msg.chat.id, $message)
|
|
||||||
.reply_markup(markup)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
$crate::change_state!(dialogue, &previous, (), State::GetExistingName, $next_func)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! simple_state_handler {
|
macro_rules! simple_state_handler {
|
||||||
($function_name: ident, $check: ident, $no_text_message: literal) => {
|
($function_name: ident, $check: ident, $no_text_message: literal) => {
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#![allow(unused)]
|
|
||||||
|
|
||||||
mod callbacks;
|
mod callbacks;
|
||||||
mod commands;
|
mod commands;
|
||||||
mod default;
|
mod default;
|
||||||
@ -49,8 +47,6 @@ fn get_dispatcher(
|
|||||||
|
|
||||||
let message_handler = Update::filter_message()
|
let message_handler = Update::filter_message()
|
||||||
.map_async(utils::delete_message)
|
.map_async(utils::delete_message)
|
||||||
.enter_dialogue::<Update, InMemStorage<State>, State>()
|
|
||||||
.branch(case![State::GetExistingName(next)].endpoint(state::get_existing_name))
|
|
||||||
.branch(case![State::GetNewName(next)].endpoint(state::get_new_name))
|
.branch(case![State::GetNewName(next)].endpoint(state::get_new_name))
|
||||||
.branch(case![State::GetMasterPass(next)].endpoint(state::get_master_pass))
|
.branch(case![State::GetMasterPass(next)].endpoint(state::get_master_pass))
|
||||||
.branch(case![State::GetNewMasterPass(next)].endpoint(state::get_new_master_pass))
|
.branch(case![State::GetNewMasterPass(next)].endpoint(state::get_new_master_pass))
|
||||||
@ -64,9 +60,12 @@ fn get_dispatcher(
|
|||||||
.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));
|
.branch(case![CallbackCommand::Get(hash)].endpoint(callbacks::get))
|
||||||
|
.branch(case![CallbackCommand::Decrypt(hash)].endpoint(callbacks::decrypt))
|
||||||
|
.branch(case![CallbackCommand::DeleteAccount(hash)].endpoint(callbacks::delete));
|
||||||
|
|
||||||
let handler = dptree::entry()
|
let handler = dptree::entry()
|
||||||
|
.enter_dialogue::<Update, InMemStorage<State>, State>()
|
||||||
.branch(message_handler)
|
.branch(message_handler)
|
||||||
.branch(callback_handler);
|
.branch(callback_handler);
|
||||||
|
|
||||||
|
@ -2,36 +2,21 @@ use crate::prelude::*;
|
|||||||
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 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};
|
||||||
use tokio::task::spawn_blocking;
|
use tokio::task::spawn_blocking;
|
||||||
|
|
||||||
/// Creates a markup of all user's account names
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn account_list_markup(
|
pub fn menu_markup_sync(
|
||||||
user_id: u64,
|
command: &str,
|
||||||
db: &DatabaseConnection,
|
names: impl IntoIterator<Item = String>,
|
||||||
) -> crate::Result<KeyboardMarkup> {
|
) -> InlineKeyboardMarkup {
|
||||||
let account_names: Vec<Vec<KeyboardButton>> = Account::get_names(user_id, db)
|
|
||||||
.await?
|
|
||||||
.map_ok(KeyboardButton::new)
|
|
||||||
.try_chunks(3)
|
|
||||||
.map_err(|err| err.1)
|
|
||||||
.try_collect()
|
|
||||||
.await?;
|
|
||||||
let markup = KeyboardMarkup::new(account_names)
|
|
||||||
.resize_keyboard(true)
|
|
||||||
.one_time_keyboard(true);
|
|
||||||
Ok(markup)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
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| {
|
||||||
let hash = <Sha256 as Digest>::digest(name.as_bytes());
|
let hash = <Sha256 as Digest>::digest(name.as_bytes());
|
||||||
let mut data = "get ".to_owned();
|
let mut data = command.to_owned();
|
||||||
data.reserve(43);
|
data.reserve(44);
|
||||||
|
data.push(' ');
|
||||||
B64_ENGINE.encode_string(hash, &mut data);
|
B64_ENGINE.encode_string(hash, &mut data);
|
||||||
InlineKeyboardButton::callback(name, data)
|
InlineKeyboardButton::callback(name, data)
|
||||||
})
|
})
|
||||||
@ -42,12 +27,14 @@ pub fn menu_markup_sync(names: impl IntoIterator<Item = String>) -> InlineKeyboa
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn menu_markup(
|
pub async fn menu_markup(
|
||||||
|
command: impl Into<String>,
|
||||||
user_id: u64,
|
user_id: u64,
|
||||||
db: &DatabaseConnection,
|
db: &DatabaseConnection,
|
||||||
) -> crate::Result<InlineKeyboardMarkup> {
|
) -> crate::Result<InlineKeyboardMarkup> {
|
||||||
|
let command: String = command.into();
|
||||||
let names: Vec<String> = Account::get_names(user_id, db).await?.try_collect().await?;
|
let names: Vec<String> = Account::get_names(user_id, db).await?.try_collect().await?;
|
||||||
|
|
||||||
spawn_blocking(|| menu_markup_sync(names))
|
spawn_blocking(move || menu_markup_sync(&command, names))
|
||||||
.await
|
.await
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
@ -69,26 +56,26 @@ pub fn account_markup(name: &str, is_encrypted: bool) -> InlineKeyboardMarkup {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let hash = std::str::from_utf8(&hash).unwrap();
|
let hash = std::str::from_utf8(&hash).unwrap();
|
||||||
|
|
||||||
let alter_buttons = [
|
let encryption_button = if is_encrypted {
|
||||||
|
("Decrypt", "decrypt")
|
||||||
|
} else {
|
||||||
|
("Hide", "get")
|
||||||
|
};
|
||||||
|
|
||||||
|
let main_buttons = [
|
||||||
("Alter name", "an"),
|
("Alter name", "an"),
|
||||||
("Alter login", "al"),
|
("Alter login", "al"),
|
||||||
("Alter password", "ap"),
|
("Alter password", "ap"),
|
||||||
|
encryption_button,
|
||||||
|
("Delete account", "delete"),
|
||||||
]
|
]
|
||||||
.map(|(text, command)| make_button(text, command, hash));
|
.into_iter()
|
||||||
|
.map(|(text, command)| make_button(text, command, hash))
|
||||||
let mut second_raw = Vec::new();
|
.chunks(3);
|
||||||
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");
|
let menu_button = InlineKeyboardButton::callback("Back to the menu", "get_menu");
|
||||||
|
|
||||||
InlineKeyboardMarkup::new([alter_buttons])
|
InlineKeyboardMarkup::new(&main_buttons).append_row([menu_button])
|
||||||
.append_row(second_raw)
|
|
||||||
.append_row([menu_button])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a markup with a "Delete message" button.
|
/// Creates a markup with a "Delete message" button.
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
pub(crate) use crate::{
|
pub(crate) use crate::{
|
||||||
ask_name_handler,
|
|
||||||
commands::Command,
|
commands::Command,
|
||||||
errors::*,
|
errors::*,
|
||||||
first_handler, handler,
|
first_handler, handler,
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
/// Function to handle GetExistingName state
|
|
||||||
pub async fn get_existing_name(
|
|
||||||
bot: Throttle<Bot>,
|
|
||||||
msg: Message,
|
|
||||||
db: DatabaseConnection,
|
|
||||||
dialogue: MainDialogue,
|
|
||||||
next: PackagedHandler<String>,
|
|
||||||
) -> crate::Result<()> {
|
|
||||||
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
|
||||||
|
|
||||||
let mut handler = next.lock().await;
|
|
||||||
if handler.func.is_none() {
|
|
||||||
let _ = dialogue.exit().await;
|
|
||||||
return Err(HandlerUsed.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let text = match msg.text() {
|
|
||||||
Some(text) => text.trim(),
|
|
||||||
None => {
|
|
||||||
let msg = bot
|
|
||||||
.send_message(
|
|
||||||
msg.chat.id,
|
|
||||||
"Couldn't get the text of the message. Send the name again",
|
|
||||||
)
|
|
||||||
.reply_markup(account_list_markup(user_id, &db).await?)
|
|
||||||
.await?;
|
|
||||||
handler.previous = MessageIds::from(&msg);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if text == "/cancel" {
|
|
||||||
dialogue.exit().await?;
|
|
||||||
handler
|
|
||||||
.previous
|
|
||||||
.alter_message(&bot, "Successfully cancelled", deletion_markup(), None)
|
|
||||||
.await?;
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if !Account::exists(user_id, text, &db).await? {
|
|
||||||
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(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let func = handler.func.take().unwrap();
|
|
||||||
let text = text.to_owned();
|
|
||||||
|
|
||||||
if let Err(err) = func(bot, msg, db, dialogue.clone(), handler.previous, text).await {
|
|
||||||
let _ = dialogue.exit().await;
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -39,7 +39,7 @@ impl MessageIds {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match edit.send_ref().await {
|
match edit.send_ref().await {
|
||||||
Ok(msg) => return Ok(()),
|
Ok(_) => return Ok(()),
|
||||||
Err(RequestError::Api(_)) => (),
|
Err(RequestError::Api(_)) => (),
|
||||||
Err(err) => return Err(err.into()),
|
Err(err) => return Err(err.into()),
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
//! This module consists of endpoints to handle the state
|
//! This module consists of endpoints to handle the state
|
||||||
|
|
||||||
mod generic;
|
mod generic;
|
||||||
mod get_existing_name;
|
|
||||||
mod get_login;
|
mod get_login;
|
||||||
mod get_master_pass;
|
mod get_master_pass;
|
||||||
mod get_new_master_pass;
|
mod get_new_master_pass;
|
||||||
@ -10,7 +9,6 @@ mod get_password;
|
|||||||
mod get_user;
|
mod get_user;
|
||||||
mod handler;
|
mod handler;
|
||||||
|
|
||||||
pub use get_existing_name::get_existing_name;
|
|
||||||
pub use get_login::get_login;
|
pub use get_login::get_login;
|
||||||
pub use get_master_pass::get_master_pass;
|
pub use get_master_pass::get_master_pass;
|
||||||
pub use get_new_master_pass::get_new_master_pass;
|
pub use get_new_master_pass::get_new_master_pass;
|
||||||
@ -26,7 +24,6 @@ use teloxide::dispatching::dialogue::InMemStorage;
|
|||||||
pub enum State {
|
pub enum State {
|
||||||
#[default]
|
#[default]
|
||||||
Start,
|
Start,
|
||||||
GetExistingName(PackagedHandler<String>),
|
|
||||||
GetNewName(PackagedHandler<String>),
|
GetNewName(PackagedHandler<String>),
|
||||||
GetMasterPass(PackagedHandler<String>),
|
GetMasterPass(PackagedHandler<String>),
|
||||||
GetNewMasterPass(PackagedHandler<String>),
|
GetNewMasterPass(PackagedHandler<String>),
|
||||||
|
11
src/utils.rs
11
src/utils.rs
@ -16,3 +16,14 @@ pub fn validate_field(field: &str) -> bool {
|
|||||||
.chars()
|
.chars()
|
||||||
.all(|char| !['`', '\\', '\n', '\t'].contains(&char))
|
.all(|char| !['`', '\\', '\n', '\t'].contains(&char))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn name_from_hash(
|
||||||
|
db: &DatabaseConnection,
|
||||||
|
user_id: u64,
|
||||||
|
hash: &[u8],
|
||||||
|
) -> crate::Result<Option<String>> {
|
||||||
|
let hash = hex::encode(hash);
|
||||||
|
Account::get_name_by_hash(user_id, hash, db)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user