diff --git a/Cargo.lock b/Cargo.lock index a1fd65e..0cba66a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1345,6 +1345,7 @@ dependencies = [ "migration", "parking_lot 0.12.1", "pretty_env_logger", + "rustc-hash", "sea-orm", "serde", "serde_json", @@ -1775,6 +1776,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 7c2881b..dbd8969 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ log = "0.4.17" migration = { version = "0.2.0", path = "migration" } parking_lot = "0.12.1" pretty_env_logger = "0.5.0" +rustc-hash = "1.1.0" sea-orm = { version = "0.11.3", features = ["sqlx-mysql", "runtime-tokio-rustls"] } serde = "1.0.163" serde_json = "1.0.96" diff --git a/src/state/get_user.rs b/src/state/get_user.rs index 9bcf262..d5b94d4 100644 --- a/src/state/get_user.rs +++ b/src/state/get_user.rs @@ -1,12 +1,14 @@ use crate::{ - errors::HandlerUsed, + errors::{HandlerUsed, NoUserInfo}, markups::deletion_markup, models::{DecryptedAccount, User}, utils::delete_optional, MainDialogue, }; -use futures::TryStreamExt; +use entity::prelude::*; +use futures::{future::try_join, TryStreamExt}; use itertools::Itertools; +use rustc_hash::FxHashSet; use sea_orm::prelude::*; use std::fmt::Write; use teloxide::{adaptors::Throttle, net::Download, prelude::*, types::Document}; @@ -27,7 +29,10 @@ async fn download_file(bot: &Throttle, document: &Document) -> crate::Resul } #[inline] -fn process_accounts(accounts: &mut [DecryptedAccount]) -> crate::Result> { +fn process_accounts( + accounts: &mut [DecryptedAccount], + existing_names: FxHashSet, +) -> crate::Result> { for account in accounts.iter_mut() { account.name.trim_in_place(); account.login.trim_in_place(); @@ -37,20 +42,30 @@ fn process_accounts(accounts: &mut [DecryptedAccount]) -> crate::Result crate::Result crate::Result) -> crate::Result> { +fn user_from_vec( + vector: Vec, + existing_names: FxHashSet, +) -> crate::Result> { let mut user: User = serde_json::from_slice(&vector)?; drop(vector); - match process_accounts(&mut user.accounts)? { + match process_accounts(&mut user.accounts, existing_names)? { Ok(()) => Ok(Ok(user)), Err(error_text) => Ok(Err(error_text)), } @@ -95,6 +121,7 @@ pub async fn get_user( dialogue: MainDialogue, next: super::PackagedHandler, ) -> crate::Result<()> { + let user_id = msg.from().ok_or(NoUserInfo)?.id.0; let mut handler = next.lock().await; delete_optional(&bot, handler.previous.as_ref()).await; @@ -136,9 +163,17 @@ pub async fn get_user( } } - let data = download_file(&bot, document).await?; + let existing_names = async { + Account::get_names(user_id, &db) + .await? + .try_collect::>() + .await + .map_err(Into::into) + }; - let user = match spawn_blocking(move || user_from_vec(data)).await? { + let (data, existing_names) = try_join(download_file(&bot, document), existing_names).await?; + + let user = match spawn_blocking(move || user_from_vec(data, existing_names)).await? { Ok(Ok(user)) => user, Ok(Err(error_text)) => { let msg = bot.send_message(msg.chat.id, error_text).await?;