Added checks if the account already exists in the database
This commit is contained in:
parent
be76b09427
commit
497e0ba5bf
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -1345,6 +1345,7 @@ dependencies = [
|
|||||||
"migration",
|
"migration",
|
||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
"pretty_env_logger",
|
"pretty_env_logger",
|
||||||
|
"rustc-hash",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -1775,6 +1776,12 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -23,6 +23,7 @@ log = "0.4.17"
|
|||||||
migration = { version = "0.2.0", path = "migration" }
|
migration = { version = "0.2.0", path = "migration" }
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
pretty_env_logger = "0.5.0"
|
pretty_env_logger = "0.5.0"
|
||||||
|
rustc-hash = "1.1.0"
|
||||||
sea-orm = { version = "0.11.3", features = ["sqlx-mysql", "runtime-tokio-rustls"] }
|
sea-orm = { version = "0.11.3", features = ["sqlx-mysql", "runtime-tokio-rustls"] }
|
||||||
serde = "1.0.163"
|
serde = "1.0.163"
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.96"
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
errors::HandlerUsed,
|
errors::{HandlerUsed, NoUserInfo},
|
||||||
markups::deletion_markup,
|
markups::deletion_markup,
|
||||||
models::{DecryptedAccount, User},
|
models::{DecryptedAccount, User},
|
||||||
utils::delete_optional,
|
utils::delete_optional,
|
||||||
MainDialogue,
|
MainDialogue,
|
||||||
};
|
};
|
||||||
use futures::TryStreamExt;
|
use entity::prelude::*;
|
||||||
|
use futures::{future::try_join, TryStreamExt};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
use sea_orm::prelude::*;
|
use sea_orm::prelude::*;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use teloxide::{adaptors::Throttle, net::Download, prelude::*, types::Document};
|
use teloxide::{adaptors::Throttle, net::Download, prelude::*, types::Document};
|
||||||
@ -27,7 +29,10 @@ async fn download_file(bot: &Throttle<Bot>, document: &Document) -> crate::Resul
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn process_accounts(accounts: &mut [DecryptedAccount]) -> crate::Result<Result<(), String>> {
|
fn process_accounts(
|
||||||
|
accounts: &mut [DecryptedAccount],
|
||||||
|
existing_names: FxHashSet<String>,
|
||||||
|
) -> crate::Result<Result<(), String>> {
|
||||||
for account in accounts.iter_mut() {
|
for account in accounts.iter_mut() {
|
||||||
account.name.trim_in_place();
|
account.name.trim_in_place();
|
||||||
account.login.trim_in_place();
|
account.login.trim_in_place();
|
||||||
@ -37,20 +42,30 @@ fn process_accounts(accounts: &mut [DecryptedAccount]) -> crate::Result<Result<(
|
|||||||
accounts.sort_unstable_by(|a, b| a.name.cmp(&b.name));
|
accounts.sort_unstable_by(|a, b| a.name.cmp(&b.name));
|
||||||
|
|
||||||
let mut duplicates = Vec::new();
|
let mut duplicates = Vec::new();
|
||||||
|
let mut existing = Vec::new();
|
||||||
let mut invalid = Vec::new();
|
let mut invalid = Vec::new();
|
||||||
|
|
||||||
accounts
|
accounts
|
||||||
.iter()
|
.iter()
|
||||||
.dedup_by_with_count(|a, b| a.name == b.name)
|
.dedup_by_with_count(|a, b| a.name == b.name)
|
||||||
.for_each(|(count, account)| {
|
.for_each(|(count, account)| {
|
||||||
if count != 1 {
|
let duplicate = count != 1;
|
||||||
|
let exists = existing_names.contains(&account.name);
|
||||||
|
if duplicate {
|
||||||
duplicates.push(account.name.as_str());
|
duplicates.push(account.name.as_str());
|
||||||
} else if !account.validate() {
|
}
|
||||||
|
if exists {
|
||||||
|
existing.push(account.name.as_str())
|
||||||
|
}
|
||||||
|
// If it already exists or if it is a duplicate there's no need to check the account's validity
|
||||||
|
if !duplicate && !exists && !account.validate() {
|
||||||
invalid.push(account.name.as_str());
|
invalid.push(account.name.as_str());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if duplicates.is_empty() && invalid.is_empty() {
|
drop(existing_names);
|
||||||
|
|
||||||
|
if duplicates.is_empty() && invalid.is_empty() && existing.is_empty() {
|
||||||
return Ok(Ok(()));
|
return Ok(Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +79,14 @@ fn process_accounts(accounts: &mut [DecryptedAccount]) -> crate::Result<Result<(
|
|||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !existing.is_empty() {
|
||||||
|
write!(
|
||||||
|
error_text,
|
||||||
|
"\n\nAccounts with these names already exist in the database:\n{:?}",
|
||||||
|
existing.into_iter().format("\n")
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
|
||||||
if !invalid.is_empty() {
|
if !invalid.is_empty() {
|
||||||
write!(
|
write!(
|
||||||
error_text,
|
error_text,
|
||||||
@ -78,10 +101,13 @@ fn process_accounts(accounts: &mut [DecryptedAccount]) -> crate::Result<Result<(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn user_from_vec(vector: Vec<u8>) -> crate::Result<Result<User, String>> {
|
fn user_from_vec(
|
||||||
|
vector: Vec<u8>,
|
||||||
|
existing_names: FxHashSet<String>,
|
||||||
|
) -> crate::Result<Result<User, String>> {
|
||||||
let mut user: User = serde_json::from_slice(&vector)?;
|
let mut user: User = serde_json::from_slice(&vector)?;
|
||||||
drop(vector);
|
drop(vector);
|
||||||
match process_accounts(&mut user.accounts)? {
|
match process_accounts(&mut user.accounts, existing_names)? {
|
||||||
Ok(()) => Ok(Ok(user)),
|
Ok(()) => Ok(Ok(user)),
|
||||||
Err(error_text) => Ok(Err(error_text)),
|
Err(error_text) => Ok(Err(error_text)),
|
||||||
}
|
}
|
||||||
@ -95,6 +121,7 @@ pub async fn get_user(
|
|||||||
dialogue: MainDialogue,
|
dialogue: MainDialogue,
|
||||||
next: super::PackagedHandler<User>,
|
next: super::PackagedHandler<User>,
|
||||||
) -> crate::Result<()> {
|
) -> crate::Result<()> {
|
||||||
|
let user_id = msg.from().ok_or(NoUserInfo)?.id.0;
|
||||||
let mut handler = next.lock().await;
|
let mut handler = next.lock().await;
|
||||||
delete_optional(&bot, handler.previous.as_ref()).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::<FxHashSet<_>>()
|
||||||
|
.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(Ok(user)) => user,
|
||||||
Ok(Err(error_text)) => {
|
Ok(Err(error_text)) => {
|
||||||
let msg = bot.send_message(msg.chat.id, error_text).await?;
|
let msg = bot.send_message(msg.chat.id, error_text).await?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user