First steps
This commit is contained in:
parent
0f6712b414
commit
ecf74fb50f
33
Cargo.lock
generated
33
Cargo.lock
generated
@ -66,9 +66,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.70"
|
version = "1.0.71"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
|
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aquamarine"
|
name = "aquamarine"
|
||||||
@ -480,9 +480,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.2.24"
|
version = "3.2.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eef2b3ded6a26dfaec672a742c93c8cf6b689220324da509ec5caa20de55dc83"
|
checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@ -494,9 +494,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "3.2.24"
|
version = "3.2.25"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d756c5824fc5c0c1ee8e36000f576968dbcb2081def956c83fad6f40acd46f96"
|
checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.4.1",
|
"heck 0.4.1",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
@ -1324,9 +1324,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.3.4"
|
version = "0.3.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf"
|
checksum = "b64f40e5e03e0d54f03845c8197d0291253cdbedfb1cb46b13c2c117554a9f4c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@ -1888,9 +1888,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.16"
|
version = "0.11.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254"
|
checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -2017,9 +2017,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.37.15"
|
version = "0.37.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece"
|
checksum = "8bbfc1d1c7c40c01715f47d71444744a81669ca84e8b63e25a55e169b1f86433"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
@ -2823,10 +2823,11 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.38"
|
version = "0.1.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf9cf6a813d3f40c88b0b6b6f29a5c95c6cdbf97c1f9cc53fb820200f5ad814d"
|
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
"log",
|
"log",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tracing-attributes",
|
"tracing-attributes",
|
||||||
@ -2958,9 +2959,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.3.1"
|
version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb"
|
checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
use crate::{entity::account, utils::handle_master_password_check};
|
|
||||||
use sea_orm::prelude::*;
|
|
||||||
use teloxide::{adaptors::Throttle, prelude::*};
|
|
||||||
|
|
||||||
pub async fn add_account(
|
|
||||||
bot: Throttle<Bot>,
|
|
||||||
msg: Message,
|
|
||||||
db: DatabaseConnection,
|
|
||||||
(name, login, password, master_pass): (String, String, String, String),
|
|
||||||
) -> crate::Result<()> {
|
|
||||||
let user_id = msg.from().unwrap().id.0;
|
|
||||||
if handle_master_password_check(&bot, &db, msg.chat.id, user_id, &master_pass).await? {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
let account =
|
|
||||||
account::ActiveModel::from_unencrypted(user_id, name, &login, &password, &master_pass)?;
|
|
||||||
account.insert(&db).await?;
|
|
||||||
bot.send_message(msg.chat.id, "Success").await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
100
src/handlers/commands/add_account.rs
Normal file
100
src/handlers/commands/add_account.rs
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
use crate::entity::account;
|
||||||
|
use crate::handlers::{utils::package_handler, MainDialogue, State};
|
||||||
|
use sea_orm::prelude::*;
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
|
||||||
|
async fn get_master_pass(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
name: String,
|
||||||
|
login: String,
|
||||||
|
password: String,
|
||||||
|
master_pass: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let _ = bot.delete_message(msg.chat.id, msg.id).await;
|
||||||
|
dialogue.exit().await?;
|
||||||
|
let account = account::ActiveModel::from_unencrypted(
|
||||||
|
msg.from().unwrap().id.0,
|
||||||
|
name,
|
||||||
|
&login,
|
||||||
|
&password,
|
||||||
|
&master_pass,
|
||||||
|
)?;
|
||||||
|
account.insert(&db).await?;
|
||||||
|
bot.send_message(msg.chat.id, "Success").await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_password(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
_: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
name: String,
|
||||||
|
login: String,
|
||||||
|
password: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let _ = bot.delete_message(msg.chat.id, msg.id).await;
|
||||||
|
bot.send_message(msg.chat.id, "Send master password")
|
||||||
|
.await?;
|
||||||
|
dialogue
|
||||||
|
.update(State::GetMasterPass(package_handler(
|
||||||
|
move |bot, msg, db, dialogue, master_pass| {
|
||||||
|
get_master_pass(bot, msg, db, dialogue, name, login, password, master_pass)
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_login(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
_: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
name: String,
|
||||||
|
login: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let _ = bot.delete_message(msg.chat.id, msg.id).await;
|
||||||
|
bot.send_message(msg.chat.id, "Send password").await?;
|
||||||
|
dialogue
|
||||||
|
.update(State::GetPassword(package_handler(
|
||||||
|
move |bot, msg, db, dialogue, password| {
|
||||||
|
get_password(bot, msg, db, dialogue, name, login, password)
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_account_name(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
_: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
name: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let _ = bot.delete_message(msg.chat.id, msg.id).await;
|
||||||
|
bot.send_message(msg.chat.id, "Send login").await?;
|
||||||
|
dialogue
|
||||||
|
.update(State::GetLogin(package_handler(
|
||||||
|
move |bot, msg, db, dialogue, login| get_login(bot, msg, db, dialogue, name, login),
|
||||||
|
)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn add_account(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
_: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
bot.send_message(msg.chat.id, "Send account name").await?;
|
||||||
|
dialogue
|
||||||
|
.update(State::GetAccountName(package_handler(get_account_name)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
61
src/handlers/commands/get_account.rs
Normal file
61
src/handlers/commands/get_account.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use crate::entity::{account, prelude::Account};
|
||||||
|
use sea_orm::prelude::*;
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode};
|
||||||
|
|
||||||
|
use crate::handlers::{utils::package_handler, MainDialogue, State};
|
||||||
|
|
||||||
|
async fn get_master_pass(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
name: String,
|
||||||
|
master_pass: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
dialogue.exit().await?;
|
||||||
|
let user_id = msg.from().unwrap().id.0;
|
||||||
|
let account = Account::find()
|
||||||
|
.filter(account::Column::UserId.eq(user_id))
|
||||||
|
.filter(account::Column::Name.eq(&name))
|
||||||
|
.one(&db)
|
||||||
|
.await?
|
||||||
|
.unwrap();
|
||||||
|
let (login, password) = account.decrypt(&master_pass)?;
|
||||||
|
let message = format!("Name:\n`{name}`\nLogin:\n`{login}`\nPassword:\n`{password}`");
|
||||||
|
bot.send_message(msg.chat.id, message)
|
||||||
|
.parse_mode(ParseMode::MarkdownV2)
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_account_name(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
_: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
name: String,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let _ = bot.delete_message(msg.chat.id, msg.id).await;
|
||||||
|
bot.send_message(msg.chat.id, "Send master password")
|
||||||
|
.await?;
|
||||||
|
dialogue
|
||||||
|
.update(State::GetMasterPass(package_handler(
|
||||||
|
move |bot, msg, db, dialogue, master_pass| {
|
||||||
|
get_master_pass(bot, msg, db, dialogue, name, master_pass)
|
||||||
|
},
|
||||||
|
)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_account(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
bot.send_message(msg.chat.id, "Send account name").await?;
|
||||||
|
dialogue
|
||||||
|
.update(State::GetAccountName(package_handler(get_account_name)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,7 +1,8 @@
|
|||||||
|
use crate::handlers::Command;
|
||||||
use teloxide::{adaptors::Throttle, prelude::*, utils::command::BotCommands};
|
use teloxide::{adaptors::Throttle, prelude::*, utils::command::BotCommands};
|
||||||
|
|
||||||
pub async fn help(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> {
|
pub async fn help(bot: Throttle<Bot>, msg: Message) -> crate::Result<()> {
|
||||||
bot.send_message(msg.chat.id, super::Command::descriptions().to_string())
|
bot.send_message(msg.chat.id, Command::descriptions().to_string())
|
||||||
.await?;
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
13
src/handlers/commands/mod.rs
Normal file
13
src/handlers/commands/mod.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
mod add_account;
|
||||||
|
mod default;
|
||||||
|
mod get_account;
|
||||||
|
mod get_accounts;
|
||||||
|
mod help;
|
||||||
|
mod set_master_pass;
|
||||||
|
|
||||||
|
pub use add_account::add_account;
|
||||||
|
pub use default::default;
|
||||||
|
pub use get_account::get_account;
|
||||||
|
pub use get_accounts::get_accounts;
|
||||||
|
pub use help::help;
|
||||||
|
pub use set_master_pass::set_master_pass;
|
@ -1,14 +1,19 @@
|
|||||||
use crate::entity::{master_pass, prelude::*};
|
use crate::{
|
||||||
|
entity::{master_pass, prelude::*},
|
||||||
|
handlers::{utils::package_handler, MainDialogue, State},
|
||||||
|
};
|
||||||
use sea_orm::{prelude::*, QuerySelect};
|
use sea_orm::{prelude::*, QuerySelect};
|
||||||
use teloxide::{adaptors::Throttle, prelude::*};
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
|
||||||
pub async fn set_master_pass(
|
async fn get_master_pass(
|
||||||
bot: Throttle<Bot>,
|
bot: Throttle<Bot>,
|
||||||
msg: Message,
|
msg: Message,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
master_pass: String,
|
dialogue: MainDialogue,
|
||||||
|
master_password: String,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
dialogue.exit().await?;
|
||||||
let user_id = msg.from().unwrap().id.0;
|
let user_id = msg.from().unwrap().id.0;
|
||||||
let exists = MasterPass::find()
|
let exists = MasterPass::find()
|
||||||
.select_only()
|
.select_only()
|
||||||
@ -24,10 +29,23 @@ pub async fn set_master_pass(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let model = task::spawn_blocking(move || {
|
let model = task::spawn_blocking(move || {
|
||||||
master_pass::ActiveModel::from_unencrypted(user_id, &master_pass)
|
master_pass::ActiveModel::from_unencrypted(user_id, &master_password)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
model.insert(&db).await?;
|
model.insert(&db).await?;
|
||||||
bot.send_message(msg.chat.id, "Success").await?;
|
bot.send_message(msg.chat.id, "Success").await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn set_master_pass(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
bot.send_message(msg.chat.id, "Send new master password")
|
||||||
|
.await?;
|
||||||
|
dialogue
|
||||||
|
.update(State::GetPassword(package_handler(get_master_pass)))
|
||||||
|
.await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -1,33 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
entity::{account, prelude::Account},
|
|
||||||
utils::handle_master_password_check,
|
|
||||||
};
|
|
||||||
use sea_orm::prelude::*;
|
|
||||||
use teloxide::{adaptors::Throttle, prelude::*, types::ParseMode};
|
|
||||||
|
|
||||||
pub async fn get_account(
|
|
||||||
bot: Throttle<Bot>,
|
|
||||||
msg: Message,
|
|
||||||
db: DatabaseConnection,
|
|
||||||
(name, master_pass): (String, String),
|
|
||||||
) -> crate::Result<()> {
|
|
||||||
let user_id = msg.from().unwrap().id.0;
|
|
||||||
if handle_master_password_check(&bot, &db, msg.chat.id, user_id, &master_pass).await? {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
let account = Account::find()
|
|
||||||
.filter(
|
|
||||||
account::Column::UserId
|
|
||||||
.eq(user_id)
|
|
||||||
.add(account::Column::Name.eq(&name)),
|
|
||||||
)
|
|
||||||
.one(&db)
|
|
||||||
.await?
|
|
||||||
.unwrap();
|
|
||||||
let (login, password) = account.decrypt(&master_pass)?;
|
|
||||||
let message = format!("Name:\n`{name}`\nLogin:\n`{login}`\nPassword:\n`{password}`");
|
|
||||||
bot.send_message(msg.chat.id, message)
|
|
||||||
.parse_mode(ParseMode::MarkdownV2)
|
|
||||||
.await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,63 +1,87 @@
|
|||||||
use sea_orm::prelude::*;
|
use sea_orm::prelude::*;
|
||||||
|
use std::sync::Arc;
|
||||||
use teloxide::{
|
use teloxide::{
|
||||||
adaptors::{throttle::Limits, Throttle},
|
adaptors::{throttle::Limits, Throttle},
|
||||||
|
dispatching::dialogue::InMemStorage,
|
||||||
filter_command,
|
filter_command,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
utils::command::BotCommands,
|
utils::command::BotCommands,
|
||||||
};
|
};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
mod add_account;
|
mod commands;
|
||||||
mod default;
|
mod state;
|
||||||
mod get_account;
|
mod utils;
|
||||||
mod get_accounts;
|
|
||||||
mod help;
|
|
||||||
mod set_master_pass;
|
|
||||||
|
|
||||||
#[derive(BotCommands, Clone)]
|
#[derive(BotCommands, Clone, Copy)]
|
||||||
#[command(rename_rule = "snake_case")]
|
#[command(rename_rule = "snake_case")]
|
||||||
enum Command {
|
enum Command {
|
||||||
#[command()]
|
#[command()]
|
||||||
Help,
|
Help,
|
||||||
#[command(parse_with = "split")]
|
#[command()]
|
||||||
AddAccount(String, String, String, String),
|
AddAccount,
|
||||||
#[command(parse_with = "split")]
|
#[command()]
|
||||||
GetAccount(String, String),
|
GetAccount,
|
||||||
#[command()]
|
#[command()]
|
||||||
GetAccounts,
|
GetAccounts,
|
||||||
#[command()]
|
#[command()]
|
||||||
SetMasterPass(String),
|
SetMasterPass,
|
||||||
|
}
|
||||||
|
|
||||||
|
type MainDialogue = Dialogue<State, InMemStorage<State>>;
|
||||||
|
type PackagedHandler<T> = Arc<
|
||||||
|
Mutex<
|
||||||
|
Option<
|
||||||
|
Box<
|
||||||
|
dyn FnOnce(
|
||||||
|
Throttle<Bot>,
|
||||||
|
Message,
|
||||||
|
DatabaseConnection,
|
||||||
|
MainDialogue,
|
||||||
|
T,
|
||||||
|
) -> crate::PinnedFuture<'static, crate::Result<()>>
|
||||||
|
+ Send
|
||||||
|
+ Sync,
|
||||||
|
>,
|
||||||
|
>,
|
||||||
|
>,
|
||||||
|
>;
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
pub enum State {
|
||||||
|
#[default]
|
||||||
|
Start,
|
||||||
|
GetAccountName(PackagedHandler<String>),
|
||||||
|
GetMasterPass(PackagedHandler<String>),
|
||||||
|
GetLogin(PackagedHandler<String>),
|
||||||
|
GetPassword(PackagedHandler<String>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_dispatcher(
|
pub fn get_dispatcher(
|
||||||
token: String,
|
token: String,
|
||||||
db: DatabaseConnection,
|
db: DatabaseConnection,
|
||||||
) -> Dispatcher<Throttle<Bot>, crate::Error, teloxide::dispatching::DefaultKey> {
|
) -> Dispatcher<Throttle<Bot>, crate::Error, teloxide::dispatching::DefaultKey> {
|
||||||
|
use dptree::{case, deps, endpoint};
|
||||||
let bot = Bot::new(token).throttle(Limits::default());
|
let bot = Bot::new(token).throttle(Limits::default());
|
||||||
Dispatcher::builder(
|
|
||||||
bot,
|
let command_handler = filter_command::<Command, _>()
|
||||||
Update::filter_message()
|
.branch(case![Command::Help].endpoint(commands::help))
|
||||||
.branch(
|
.branch(case![Command::AddAccount].endpoint(commands::add_account))
|
||||||
filter_command::<Command, _>()
|
.branch(case![Command::GetAccount].endpoint(commands::get_account))
|
||||||
.branch(dptree::case![Command::Help].endpoint(help::help))
|
.branch(case![Command::GetAccounts].endpoint(commands::get_accounts))
|
||||||
.branch(
|
.branch(case![Command::SetMasterPass].endpoint(commands::set_master_pass));
|
||||||
dptree::case![Command::AddAccount(name, login, password, master_pass)]
|
|
||||||
.endpoint(add_account::add_account),
|
let message_handler = Update::filter_message()
|
||||||
)
|
.enter_dialogue::<Update, InMemStorage<State>, State>()
|
||||||
.branch(
|
.branch(command_handler)
|
||||||
dptree::case![Command::GetAccount(name, master_pass)]
|
.branch(case![State::GetAccountName(next)].endpoint(state::get_account_name))
|
||||||
.endpoint(get_account::get_account),
|
.branch(case![State::GetMasterPass(next)].endpoint(state::get_master_pass))
|
||||||
)
|
.branch(case![State::GetLogin(next)].endpoint(state::get_login))
|
||||||
.branch(
|
.branch(case![State::GetPassword(next)].endpoint(state::get_password))
|
||||||
dptree::case![Command::GetAccounts].endpoint(get_accounts::get_accounts),
|
.branch(endpoint(commands::default));
|
||||||
)
|
|
||||||
.branch(
|
Dispatcher::builder(bot, message_handler)
|
||||||
dptree::case![Command::SetMasterPass(param)]
|
.dependencies(deps![db, InMemStorage::<State>::new()])
|
||||||
.endpoint(set_master_pass::set_master_pass),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.branch(dptree::endpoint(default::default)),
|
|
||||||
)
|
|
||||||
.dependencies(dptree::deps![db])
|
|
||||||
.enable_ctrlc_handler()
|
.enable_ctrlc_handler()
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
37
src/handlers/state/generic.rs
Normal file
37
src/handlers/state/generic.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use sea_orm::prelude::*;
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
|
||||||
|
use crate::PinnedFuture;
|
||||||
|
|
||||||
|
pub async fn generic<F>(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
text: String,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: crate::handlers::MainDialogue,
|
||||||
|
check: F,
|
||||||
|
next: crate::handlers::PackagedHandler<String>,
|
||||||
|
) -> crate::Result<()>
|
||||||
|
where
|
||||||
|
for<'a> F: FnOnce(
|
||||||
|
&'a Throttle<Bot>,
|
||||||
|
&'a Message,
|
||||||
|
&'a DatabaseConnection,
|
||||||
|
&'a str,
|
||||||
|
) -> PinnedFuture<'a, crate::Result<bool>>,
|
||||||
|
{
|
||||||
|
if text == "/cancel" {
|
||||||
|
dialogue.exit().await?;
|
||||||
|
bot.send_message(msg.chat.id, "Successfully cancelled")
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
match check(&bot, &msg, &db, &text).await {
|
||||||
|
Ok(true) => (),
|
||||||
|
Ok(false) => dialogue.exit().await?,
|
||||||
|
Err(err) => {
|
||||||
|
let _ = dialogue.exit().await;
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
next.lock().await.take().unwrap()(bot, msg, db, dialogue, text).await
|
||||||
|
}
|
24
src/handlers/state/get_account_name.rs
Normal file
24
src/handlers/state/get_account_name.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use sea_orm::prelude::*;
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
|
||||||
|
use crate::handlers::{MainDialogue, PackagedHandler};
|
||||||
|
|
||||||
|
pub async fn get_account_name(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
next: PackagedHandler<String>,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let text = msg.text().unwrap().trim().to_owned();
|
||||||
|
super::generic::generic(
|
||||||
|
bot,
|
||||||
|
text,
|
||||||
|
msg,
|
||||||
|
db,
|
||||||
|
dialogue,
|
||||||
|
|_, _, _, _| Box::pin(async { Ok(true) }),
|
||||||
|
next,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
24
src/handlers/state/get_login.rs
Normal file
24
src/handlers/state/get_login.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use sea_orm::prelude::*;
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
|
||||||
|
use crate::handlers::{MainDialogue, PackagedHandler};
|
||||||
|
|
||||||
|
pub async fn get_login(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
next: PackagedHandler<String>,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let text = msg.text().unwrap().trim().to_owned();
|
||||||
|
super::generic::generic(
|
||||||
|
bot,
|
||||||
|
text,
|
||||||
|
msg,
|
||||||
|
db,
|
||||||
|
dialogue,
|
||||||
|
|_, _, _, _| Box::pin(async { Ok(true) }),
|
||||||
|
next,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
50
src/handlers/state/get_master_pass.rs
Normal file
50
src/handlers/state/get_master_pass.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
use crate::{
|
||||||
|
entity::prelude::MasterPass,
|
||||||
|
handlers::{MainDialogue, PackagedHandler},
|
||||||
|
};
|
||||||
|
use sea_orm::prelude::*;
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub async fn check_master_pass<'a>(
|
||||||
|
bot: &'a Throttle<Bot>,
|
||||||
|
msg: &'a Message,
|
||||||
|
db: &'a DatabaseConnection,
|
||||||
|
master_pass: &'a str,
|
||||||
|
) -> crate::Result<bool> {
|
||||||
|
let result = MasterPass::verify_master_pass(msg.from().unwrap().id.0, master_pass, db).await;
|
||||||
|
match result {
|
||||||
|
Ok(Some(true)) => Ok(true),
|
||||||
|
Ok(Some(false)) => {
|
||||||
|
bot.send_message(msg.chat.id, "Wrong master password")
|
||||||
|
.await?;
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
Ok(None) => {
|
||||||
|
bot.send_message(msg.chat.id, "No master password set")
|
||||||
|
.await?;
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
Err(err) => Err(err.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_master_pass(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
next: PackagedHandler<String>,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let text = msg.text().unwrap().trim().to_owned();
|
||||||
|
super::generic::generic(
|
||||||
|
bot,
|
||||||
|
text,
|
||||||
|
msg,
|
||||||
|
db,
|
||||||
|
dialogue,
|
||||||
|
|bot, msg, db, text| Box::pin(check_master_pass(bot, msg, db, text)),
|
||||||
|
next,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
24
src/handlers/state/get_password.rs
Normal file
24
src/handlers/state/get_password.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use sea_orm::prelude::*;
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
|
||||||
|
use crate::handlers::{MainDialogue, PackagedHandler};
|
||||||
|
|
||||||
|
pub async fn get_password(
|
||||||
|
bot: Throttle<Bot>,
|
||||||
|
msg: Message,
|
||||||
|
db: DatabaseConnection,
|
||||||
|
dialogue: MainDialogue,
|
||||||
|
next: PackagedHandler<String>,
|
||||||
|
) -> crate::Result<()> {
|
||||||
|
let text = msg.text().unwrap().trim().to_owned();
|
||||||
|
super::generic::generic(
|
||||||
|
bot,
|
||||||
|
text,
|
||||||
|
msg,
|
||||||
|
db,
|
||||||
|
dialogue,
|
||||||
|
|_, _, _, _| Box::pin(async { Ok(true) }),
|
||||||
|
next,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
10
src/handlers/state/mod.rs
Normal file
10
src/handlers/state/mod.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
mod generic;
|
||||||
|
mod get_account_name;
|
||||||
|
mod get_login;
|
||||||
|
mod get_master_pass;
|
||||||
|
mod get_password;
|
||||||
|
|
||||||
|
pub use get_account_name::get_account_name;
|
||||||
|
pub use get_login::get_login;
|
||||||
|
pub use get_master_pass::get_master_pass;
|
||||||
|
pub use get_password::get_password;
|
19
src/handlers/utils.rs
Normal file
19
src/handlers/utils.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use super::{MainDialogue, PackagedHandler};
|
||||||
|
use sea_orm::DatabaseConnection;
|
||||||
|
use std::{future::Future, sync::Arc};
|
||||||
|
use teloxide::{adaptors::Throttle, prelude::*};
|
||||||
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn package_handler<H, F, T>(f: H) -> PackagedHandler<T>
|
||||||
|
where
|
||||||
|
H: FnOnce(Throttle<Bot>, Message, DatabaseConnection, MainDialogue, T) -> F
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
F: Future<Output = crate::Result<()>> + Send + 'static,
|
||||||
|
{
|
||||||
|
Arc::new(Mutex::new(Some(Box::new(
|
||||||
|
move |bot, msg, db, dialogue, val| Box::pin(f(bot, msg, db, dialogue, val)),
|
||||||
|
))))
|
||||||
|
}
|
@ -1,13 +1,14 @@
|
|||||||
mod entity;
|
mod entity;
|
||||||
mod handlers;
|
mod handlers;
|
||||||
mod utils;
|
|
||||||
|
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use handlers::get_dispatcher;
|
use handlers::get_dispatcher;
|
||||||
use migration::{Migrator, MigratorTrait};
|
use migration::{Migrator, MigratorTrait};
|
||||||
use sea_orm::Database;
|
use sea_orm::Database;
|
||||||
use std::env;
|
use std::{env, future::Future, pin::Pin};
|
||||||
|
|
||||||
|
type PinnedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
34
src/utils.rs
34
src/utils.rs
@ -1,34 +0,0 @@
|
|||||||
use crate::entity::prelude::*;
|
|
||||||
use sea_orm::DatabaseConnection;
|
|
||||||
use teloxide::{adaptors::Throttle, prelude::*};
|
|
||||||
|
|
||||||
/// Handles checking the master password
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
///
|
|
||||||
/// Returns Ok(true) if the master password wasn't right or if it wasn't set
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns an error if there was an error getting or hashing the master password
|
|
||||||
#[inline]
|
|
||||||
pub async fn handle_master_password_check(
|
|
||||||
bot: &Throttle<Bot>,
|
|
||||||
db: &DatabaseConnection,
|
|
||||||
chat_id: ChatId,
|
|
||||||
user_id: u64,
|
|
||||||
master_pass: &str,
|
|
||||||
) -> crate::Result<bool> {
|
|
||||||
match MasterPass::verify_master_pass(user_id, &master_pass, db).await {
|
|
||||||
Ok(Some(true)) => Ok(false),
|
|
||||||
Ok(Some(false)) => {
|
|
||||||
bot.send_message(chat_id, "Wrong master password").await?;
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
Ok(None) => {
|
|
||||||
bot.send_message(chat_id, "No master password set").await?;
|
|
||||||
Ok(true)
|
|
||||||
}
|
|
||||||
Err(err) => Err(err.into()),
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user