Added search

This commit is contained in:
2025-03-14 18:46:24 +03:00
parent 777ad8e311
commit bc6ede32b9
10 changed files with 431 additions and 151 deletions

View File

@ -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(())
}

View File

@ -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,