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",
|
||||
"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"
|
||||
|
@ -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"
|
||||
|
@ -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<Bot>, document: &Document) -> crate::Resul
|
||||
}
|
||||
|
||||
#[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() {
|
||||
account.name.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));
|
||||
|
||||
let mut duplicates = Vec::new();
|
||||
let mut existing = Vec::new();
|
||||
let mut invalid = Vec::new();
|
||||
|
||||
accounts
|
||||
.iter()
|
||||
.dedup_by_with_count(|a, b| a.name == b.name)
|
||||
.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());
|
||||
} 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());
|
||||
}
|
||||
});
|
||||
|
||||
if duplicates.is_empty() && invalid.is_empty() {
|
||||
drop(existing_names);
|
||||
|
||||
if duplicates.is_empty() && invalid.is_empty() && existing.is_empty() {
|
||||
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() {
|
||||
write!(
|
||||
error_text,
|
||||
@ -78,10 +101,13 @@ fn process_accounts(accounts: &mut [DecryptedAccount]) -> crate::Result<Result<(
|
||||
}
|
||||
|
||||
#[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)?;
|
||||
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<User>,
|
||||
) -> 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::<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(Err(error_text)) => {
|
||||
let msg = bot.send_message(msg.chat.id, error_text).await?;
|
||||
|
Loading…
Reference in New Issue
Block a user