Added search
This commit is contained in:
@ -1,9 +1,48 @@
|
||||
use crate::prelude::*;
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
use crate::{
|
||||
markups::{account_markup, menu_markup_sync},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
/// Handles the messages which weren't matched by any commands or states
|
||||
pub async fn default(bot: Throttle<Bot>, msg: Message, locale: LocaleRef) -> crate::Result<()> {
|
||||
bot.send_message(msg.chat.id, &locale.unknown_command_use_help)
|
||||
.reply_markup(deletion_markup(locale))
|
||||
.await?;
|
||||
pub async fn default(
|
||||
bot: Throttle<Bot>,
|
||||
msg: Message,
|
||||
db: Pool,
|
||||
locale: LocaleRef,
|
||||
) -> crate::Result<()> {
|
||||
let user_id = msg.get_user_id()?;
|
||||
|
||||
if msg.text().is_none() || !MasterPass::exists(user_id, &db).await? {
|
||||
bot.send_message(msg.chat.id, &locale.unknown_command_use_help)
|
||||
.reply_markup(deletion_markup(locale))
|
||||
.await?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let names = Account::search(user_id, msg.text().unwrap().to_owned(), &db).await?;
|
||||
|
||||
match names.as_slice() {
|
||||
[] => {
|
||||
bot.send_message(msg.chat.id, &locale.no_accounts_found)
|
||||
.reply_markup(deletion_markup(locale))
|
||||
.await?;
|
||||
}
|
||||
[name] => {
|
||||
let text = locale.show_hidden_account(name);
|
||||
bot.send_message(msg.chat.id, text)
|
||||
.reply_markup(account_markup(name, true, locale))
|
||||
.parse_mode(teloxide::types::ParseMode::MarkdownV2)
|
||||
.await?;
|
||||
}
|
||||
_ => {
|
||||
let markup = spawn_blocking(|| menu_markup_sync("get", names)).await?;
|
||||
bot.send_message(msg.chat.id, &locale.choose_account)
|
||||
.reply_markup(markup)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::Pool;
|
||||
use futures::{Stream, TryStreamExt};
|
||||
use sqlx::{Executor, FromRow, MySql, query, query_as};
|
||||
use tokio::task::spawn_blocking;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, FromRow, Default)]
|
||||
pub struct Account {
|
||||
@ -29,17 +30,17 @@ impl Account {
|
||||
|
||||
/// Gets all user's account from DB
|
||||
pub fn get_all(user_id: u64, pool: &Pool) -> impl Stream<Item = super::Result<Self>> + '_ {
|
||||
query_as("SELECT * FROM account WHERE user_id = ?")
|
||||
.bind(user_id)
|
||||
.fetch(pool)
|
||||
query_as!(Self, "SELECT * FROM account WHERE user_id = ?", user_id).fetch(pool)
|
||||
}
|
||||
|
||||
/// Streams the names of the user accounts
|
||||
pub fn get_names(user_id: u64, pool: &Pool) -> impl Stream<Item = super::Result<String>> + '_ {
|
||||
query_as::<_, (String,)>("SELECT name FROM account WHERE user_id = ? ORDER BY name")
|
||||
.bind(user_id)
|
||||
.fetch(pool)
|
||||
.map_ok(|(name,)| name)
|
||||
query!(
|
||||
"SELECT name FROM account WHERE user_id = ? ORDER BY name",
|
||||
user_id
|
||||
)
|
||||
.fetch(pool)
|
||||
.map_ok(|record| record.name)
|
||||
}
|
||||
|
||||
/// Checks if the account exists
|
||||
@ -56,11 +57,33 @@ impl Account {
|
||||
|
||||
/// Gets the account from the DB
|
||||
pub async fn get(user_id: u64, account_name: &str, pool: &Pool) -> super::Result<Option<Self>> {
|
||||
query_as("SELECT * FROM account WHERE user_id = ? AND name = ?")
|
||||
.bind(user_id)
|
||||
.bind(account_name)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
query_as!(
|
||||
Self,
|
||||
"SELECT * FROM account WHERE user_id = ? AND name = ?",
|
||||
user_id,
|
||||
account_name
|
||||
)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Searches for an account
|
||||
pub async fn search(
|
||||
user_id: u64,
|
||||
search_str: String,
|
||||
pool: &Pool,
|
||||
) -> crate::Result<Vec<String>> {
|
||||
use fuzzy_matcher::{FuzzyMatcher, skim::SkimMatcherV2};
|
||||
|
||||
let mut accounts: Vec<String> = Self::get_names(user_id, pool).try_collect().await?;
|
||||
|
||||
spawn_blocking(move || {
|
||||
let matcher = SkimMatcherV2::default().ignore_case();
|
||||
accounts.retain(|name| matcher.fuzzy_match(name, &search_str).is_some());
|
||||
accounts
|
||||
})
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
// Deletes the account from DB
|
||||
@ -93,25 +116,26 @@ impl Account {
|
||||
pool: &Pool,
|
||||
) -> super::Result<Option<String>> {
|
||||
let hash = hex::encode(hash);
|
||||
let name = query_as::<_, (String,)>(
|
||||
let name = query!(
|
||||
"SELECT `name` FROM `account` WHERE SHA2(`name`, 256) = ? AND `user_id` = ?;",
|
||||
hash,
|
||||
user_id,
|
||||
)
|
||||
.bind(hash)
|
||||
.bind(user_id)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
Ok(name.map(|(name,)| name))
|
||||
Ok(name.map(|record| record.name))
|
||||
}
|
||||
pub async fn get_salt(user_id: u64, name: &str, pool: &Pool) -> super::Result<Option<Vec<u8>>> {
|
||||
let salt =
|
||||
query_as::<_, (Vec<u8>,)>("SELECT salt FROM account WHERE user_id = ? AND name = ?")
|
||||
.bind(user_id)
|
||||
.bind(name)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
let salt = query!(
|
||||
"SELECT salt FROM account WHERE user_id = ? AND name = ?",
|
||||
user_id,
|
||||
name
|
||||
)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
Ok(salt.map(|(salt,)| salt))
|
||||
Ok(salt.map(|record| record.salt))
|
||||
}
|
||||
pub async fn update_name(
|
||||
user_id: u64,
|
||||
|
Reference in New Issue
Block a user