Updated GetUsers to provide better inforamtion about invalid accounts to a user
This commit is contained in:
@ -45,9 +45,13 @@ impl DecryptedAccount {
|
||||
/// Returns true if the account's fields are valid
|
||||
#[inline]
|
||||
pub fn validate(&self) -> bool {
|
||||
[&self.name, &self.login, &self.password]
|
||||
.into_iter()
|
||||
.all(|field| validate_field(field))
|
||||
[
|
||||
self.name.as_str(),
|
||||
self.login.as_str(),
|
||||
self.password.as_str(),
|
||||
]
|
||||
.into_iter()
|
||||
.all(validate_field)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,91 @@
|
||||
use crate::{
|
||||
errors::HandlerUsed, markups::deletion_markup, models::User, utils::delete_optional,
|
||||
errors::HandlerUsed,
|
||||
markups::deletion_markup,
|
||||
models::{DecryptedAccount, User},
|
||||
utils::delete_optional,
|
||||
MainDialogue,
|
||||
};
|
||||
use futures::TryStreamExt;
|
||||
use itertools::Itertools;
|
||||
use sea_orm::prelude::*;
|
||||
use teloxide::{adaptors::Throttle, net::Download, prelude::*};
|
||||
use std::fmt::Write;
|
||||
use teloxide::{adaptors::Throttle, net::Download, prelude::*, types::Document};
|
||||
use tokio::task::spawn_blocking;
|
||||
use trim_in_place::TrimInPlace;
|
||||
|
||||
#[inline]
|
||||
async fn download_file(bot: &Throttle<Bot>, document: &Document) -> crate::Result<Vec<u8>> {
|
||||
let path = bot.get_file(document.file.id.as_str()).await?.path;
|
||||
let mut data = Vec::with_capacity(document.file.size as usize);
|
||||
bot.download_file_stream(&path)
|
||||
.try_for_each(|bytes| {
|
||||
data.extend(bytes);
|
||||
async { Ok(()) }
|
||||
})
|
||||
.await?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn process_accounts(accounts: &mut [DecryptedAccount]) -> crate::Result<Result<(), String>> {
|
||||
for account in accounts.iter_mut() {
|
||||
account.name.trim_in_place();
|
||||
account.login.trim_in_place();
|
||||
account.password.trim_in_place();
|
||||
}
|
||||
|
||||
accounts.sort_unstable_by(|a, b| a.name.cmp(&b.name));
|
||||
|
||||
let mut duplicates = 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 {
|
||||
duplicates.push(account.name.as_str());
|
||||
} else if !account.validate() {
|
||||
invalid.push(account.name.as_str());
|
||||
}
|
||||
});
|
||||
|
||||
if duplicates.is_empty() && invalid.is_empty() {
|
||||
return Ok(Ok(()));
|
||||
}
|
||||
|
||||
let mut error_text = "Your accounts have the following problems:".to_owned();
|
||||
|
||||
if !duplicates.is_empty() {
|
||||
write!(
|
||||
error_text,
|
||||
"\n\nDuplicate names:\n{:?}",
|
||||
duplicates.into_iter().format("\n")
|
||||
)?
|
||||
}
|
||||
|
||||
if !invalid.is_empty() {
|
||||
write!(
|
||||
error_text,
|
||||
"\n\nInvalid account fields:\n{:?}",
|
||||
invalid.into_iter().format("\n")
|
||||
)?
|
||||
}
|
||||
|
||||
error_text.push_str("\n\nFix these problems and send the file again");
|
||||
|
||||
Ok(Err(error_text))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn user_from_vec(vector: Vec<u8>) -> crate::Result<Result<User, String>> {
|
||||
let mut user: User = serde_json::from_slice(&vector)?;
|
||||
drop(vector);
|
||||
match process_accounts(&mut user.accounts)? {
|
||||
Ok(()) => Ok(Ok(user)),
|
||||
Err(error_text) => Ok(Err(error_text)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Function to handle GetUser state. It doesn't actually validate anything
|
||||
pub async fn get_user(
|
||||
@ -56,17 +136,15 @@ pub async fn get_user(
|
||||
}
|
||||
}
|
||||
|
||||
let file = bot.get_file(&document.file.id).await?;
|
||||
let mut data = Vec::with_capacity(document.file.size as usize);
|
||||
bot.download_file_stream(&file.path)
|
||||
.try_for_each(|bytes| {
|
||||
data.extend(bytes);
|
||||
async { Ok(()) }
|
||||
})
|
||||
.await?;
|
||||
let data = download_file(&bot, document).await?;
|
||||
|
||||
let user: User = match spawn_blocking(move || serde_json::from_slice(&data)).await? {
|
||||
Ok(user) => user,
|
||||
let user = match spawn_blocking(move || user_from_vec(data)).await? {
|
||||
Ok(Ok(user)) => user,
|
||||
Ok(Err(error_text)) => {
|
||||
let msg = bot.send_message(msg.chat.id, error_text).await?;
|
||||
handler.previous = Some(msg);
|
||||
return Ok(());
|
||||
}
|
||||
Err(_) => {
|
||||
let msg = bot
|
||||
.send_message(msg.chat.id, "Error parsing the json file. Try again")
|
||||
|
@ -17,7 +17,10 @@ pub async fn delete_optional(bot: &Throttle<Bot>, msg: Option<&Message>) {
|
||||
/// Returns true if the field is valid
|
||||
#[inline]
|
||||
pub fn validate_field(field: &str) -> bool {
|
||||
if field.is_empty() {
|
||||
return false;
|
||||
}
|
||||
field
|
||||
.chars()
|
||||
.all(|char| char != '`' && char != '\\' && char != '\n')
|
||||
.all(|char| !['`', '\\', '\n', '\t'].contains(&char))
|
||||
}
|
||||
|
Reference in New Issue
Block a user