diff --git a/src/config/dialog/button.rs b/src/config/dialog/button.rs new file mode 100644 index 0000000..89d5e2c --- /dev/null +++ b/src/config/dialog/button.rs @@ -0,0 +1,119 @@ +use serde::{Deserialize, Serialize}; + +use crate::{ + config::{ + function::BotFunction, + result::{ConfigError, ConfigResult}, + traits::{ProviderDeserialize, ResolveValue}, + Provider, + }, + db::{CallDB, DB}, + notify_admin, +}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(untagged)] +pub enum ButtonDefinition { + Button(ButtonRaw), + ButtonLiteral(String), + Function(BotFunction

), +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ButtonRaw { + name: ButtonName, + callback_name: String, +} + +impl ButtonRaw { + pub fn from_literal(literal: String) -> Self { + ButtonRaw { + name: ButtonName::Literal { + literal: literal.clone(), + }, + callback_name: literal, + } + } + + pub fn name(&self) -> &ButtonName { + &self.name + } + + pub fn callback_name(&self) -> &str { + &self.callback_name + } + + pub fn literal(&self) -> Option { + match self.name() { + ButtonName::Value { .. } => None, + ButtonName::Literal { literal } => Some(literal.to_string()), + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(untagged)] +pub enum ButtonName { + Value { name: String }, + Literal { literal: String }, +} + +impl ButtonName { + pub async fn resolve_name(self, db: &mut DB) -> ConfigResult { + match self { + ButtonName::Value { name } => Ok(name), + ButtonName::Literal { literal } => { + let value = db.get_literal_value(&literal).await?; + + Ok(match value { + Some(value) => Ok(value), + None => { + notify_admin(&format!("Literal `{literal}` is not set!!!")).await; + Err(ConfigError::Other(format!( + "not found literal `{literal}` in DB" + ))) + } + }?) + } + } + } +} + +pub enum ButtonLayout { + Callback { + name: String, + literal: Option, + callback: String, + }, +} + +impl ButtonLayout { + pub async fn resolve_raw(braw: ButtonRaw, db: &mut DB) -> ConfigResult { + let name = braw.name().clone().resolve_name(db).await?; + let literal = braw.literal(); + let callback = braw.callback_name().to_string(); + Ok(Self::Callback { + name, + literal, + callback, + }) + } +} + +impl ResolveValue for ButtonDefinition

{ + type Value = ButtonRaw; + type Runtime = P; + + fn resolve(self) -> ConfigResult { + match self { + ButtonDefinition::Button(button) => Ok(button), + ButtonDefinition::ButtonLiteral(l) => Ok(ButtonRaw::from_literal(l)), + ButtonDefinition::Function(f) => ::resolve(match f.call()? { + Some(t) => Ok(t.de_into().map_err(ConfigError::as_provider_err)?), + None => Err(ConfigError::Other( + "Function didn't return value".to_string(), + )), + }?), + } + } +} diff --git a/src/config/dialog/keyboard.rs b/src/config/dialog/keyboard.rs new file mode 100644 index 0000000..448e05b --- /dev/null +++ b/src/config/dialog/keyboard.rs @@ -0,0 +1,58 @@ +use serde::{Deserialize, Serialize}; + +use crate::config::{ + function::BotFunction, + result::{ConfigError, ConfigResult}, + traits::{ProviderDeserialize, ResolveValue}, + Provider, +}; + +use super::button::ButtonDefinition; + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(untagged)] +pub enum KeyboardDefinition { + Rows(Vec>), + Function(BotFunction

), +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(untagged)] +pub enum RowDefinition { + Buttons(Vec>), + Function(BotFunction

), +} + +impl ResolveValue for KeyboardDefinition

{ + type Value = Vec< as ResolveValue>::Value>; + type Runtime = P; + + fn resolve(self) -> ConfigResult { + match self { + KeyboardDefinition::Rows(rows) => rows.into_iter().map(|r| r.resolve()).collect(), + KeyboardDefinition::Function(f) => ::resolve(match f.call()? { + Some(t) => Ok(t.de_into().map_err(ConfigError::as_provider_err)?), + None => Err(ConfigError::Other( + "Function didn't return value".to_string(), + )), + }?), + } + } +} + +impl ResolveValue for RowDefinition

{ + type Value = Vec< as ResolveValue>::Value>; + type Runtime = P; + + fn resolve(self) -> ConfigResult { + match self { + RowDefinition::Buttons(buttons) => buttons.into_iter().map(|b| b.resolve()).collect(), + RowDefinition::Function(f) => ::resolve(match f.call()? { + Some(t) => Ok(t.de_into().map_err(ConfigError::as_provider_err)?), + None => Err(ConfigError::Other( + "Function didn't return value".to_string(), + )), + }?), + } + } +} diff --git a/src/config/dialog/message.rs b/src/config/dialog/message.rs new file mode 100644 index 0000000..9779f9b --- /dev/null +++ b/src/config/dialog/message.rs @@ -0,0 +1,93 @@ +use futures::future::join_all; +use serde::{Deserialize, Serialize}; + +use crate::{ + config::{function::BotFunction, result::ConfigResult, traits::ResolveValue, Provider}, + db::DB, +}; + +use super::{button::ButtonLayout, keyboard::KeyboardDefinition}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct BotMessage { + // buttons: Vec