use crate::prelude::*; use base64::{engine::general_purpose::STANDARD_NO_PAD as B64_ENGINE, Engine as _}; use itertools::Itertools; use sha2::{Digest, Sha256}; use teloxide::types::{InlineKeyboardButton, InlineKeyboardMarkup}; use tokio::task::spawn_blocking; #[inline] pub fn menu_markup_sync( command: &str, names: impl IntoIterator, ) -> InlineKeyboardMarkup { let names = names .into_iter() .map(|name| { let hash = ::digest(name.as_bytes()); let mut data = command.to_owned(); data.reserve(44); data.push(' '); B64_ENGINE.encode_string(hash, &mut data); InlineKeyboardButton::callback(name, data) }) .chunks(3); InlineKeyboardMarkup::new(&names) } #[inline] pub async fn menu_markup( command: impl Into, user_id: u64, db: &DatabaseConnection, ) -> crate::Result { let command: String = command.into(); let names: Vec = Account::get_names(user_id, db).await?.try_collect().await?; spawn_blocking(move || menu_markup_sync(&command, names)) .await .map_err(Into::into) } #[inline] fn make_button(text: &str, command: &str, hash: &str) -> InlineKeyboardButton { let mut data = command.to_owned(); data.reserve(44); data.push(' '); data.push_str(hash); InlineKeyboardButton::callback(text, data) } #[inline] pub fn account_markup(name: &str, is_encrypted: bool) -> InlineKeyboardMarkup { let mut hash = [0; 43]; B64_ENGINE .encode_slice(::digest(name), &mut hash) .unwrap(); let hash = std::str::from_utf8(&hash).unwrap(); let encryption_button = if is_encrypted { ("Decrypt", "decrypt") } else { ("Hide", "get") }; let main_buttons = [ ("Alter name", "an"), ("Alter login", "al"), ("Alter password", "ap"), encryption_button, ("Delete account", "delete"), ] .into_iter() .map(|(text, command)| make_button(text, command, hash)) .chunks(3); let menu_button = InlineKeyboardButton::callback("Back to the menu", "get_menu"); InlineKeyboardMarkup::new(&main_buttons).append_row([menu_button]) } /// Creates a markup with a "Delete message" button. /// This markup should be added for all messages that won't be deleted afterwards #[inline] pub fn deletion_markup() -> InlineKeyboardMarkup { let button = InlineKeyboardButton::callback("Delete message", "delete_message"); InlineKeyboardMarkup::new([[button]]) }