Compare commits

...

6 Commits

Author SHA1 Message Date
Akulij
c371f81008 send /start message variants based on meta (?start=...)
All checks were successful
Build && Deploy / cargo build (push) Successful in 59s
2025-05-04 18:43:10 +03:00
Akulij
d0882ffe0b admin: create /setalternative command to edit message variants 2025-05-04 18:42:28 +03:00
Akulij
e68ba4b796 implement variant editing thru Edit state 2025-05-04 18:41:40 +03:00
Akulij
f86286b1d4 use variant in answer_message_varianted 2025-05-04 18:11:55 +03:00
Akulij
92b43aed65 extend answer_message with LiteralAlternatives in new function
answer_message_variant
2025-05-04 18:04:30 +03:00
Akulij
12567a6b97 create LiteralAlternative with get/set in db 2025-05-04 17:56:06 +03:00
3 changed files with 135 additions and 6 deletions

View File

@ -31,6 +31,9 @@ pub enum AdminCommands {
EditButton,
/// Set specified literal value
SetLiteral { literal: String },
/// Set specified literal value
#[command(description = "handle a username and an age.", parse_with = "split")]
SetAlternative { literal: String, variant: String },
/// Sets chat where this message entered as support's chats
SetChat,
}
@ -86,6 +89,7 @@ pub async fn admin_command_handler(
dialogue
.update(State::Edit {
literal,
variant: None,
lang: "ru".to_string(),
is_caption_set: false,
})
@ -95,6 +99,20 @@ pub async fn admin_command_handler(
Ok(())
}
AdminCommands::SetAlternative { literal, variant } => {
dialogue
.update(State::Edit {
literal,
variant: Some(variant),
lang: "ru".to_string(),
is_caption_set: false,
})
.await?;
bot.send_message(msg.chat.id, "Send message for literal alternative")
.await?;
Ok(())
}
AdminCommands::SetChat => {
dialogue.exit().await?;
db.set_literal("support_chat_id", &msg.chat.id.0.to_string())

View File

@ -112,6 +112,14 @@ pub struct Literal {
pub value: String,
}
#[derive(Serialize, Deserialize)]
pub struct LiteralAlternative {
pub _id: bson::oid::ObjectId,
pub token: String,
pub variant: String,
pub value: String,
}
#[derive(Serialize, Deserialize)]
pub struct Event {
pub _id: bson::oid::ObjectId,
@ -321,6 +329,51 @@ pub trait CallDB {
Ok(())
}
async fn get_literal_alternative(
&mut self,
literal: &str,
variant: &str,
) -> DbResult<Option<LiteralAlternative>> {
let db = self.get_database().await;
let messages = db.collection::<LiteralAlternative>("literal_alternatives");
let literal = messages
.find_one(doc! { "token": literal, "variant": variant })
.await?;
Ok(literal)
}
async fn get_literal_alternative_value(
&mut self,
literal: &str,
variant: &str,
) -> DbResult<Option<String>> {
let literal = self.get_literal_alternative(literal, variant).await?;
Ok(literal.map(|l| l.value))
}
async fn set_literal_alternative(
&mut self,
literal: &str,
variant: &str,
valuestr: &str,
) -> DbResult<()> {
let db = self.get_database().await;
let literals = db.collection::<LiteralAlternative>("literal_alternatives");
literals
.update_one(
doc! { "token": literal, "variant": variant },
doc! { "$set": { "value": valuestr } },
)
.upsert(true)
.await?;
Ok(())
}
async fn get_all_events(&mut self) -> DbResult<Vec<Event>> {
let db = self.get_database().await;
let events = db.collection::<Event>("events");

View File

@ -70,6 +70,7 @@ pub enum State {
Start,
Edit {
literal: String,
variant: Option<String>,
lang: String,
is_caption_set: bool,
},
@ -187,6 +188,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.branch(
dptree::case![State::Edit {
literal,
variant,
lang,
is_caption_set
}]
@ -252,6 +254,7 @@ async fn button_edit_callback(
dialogue
.update(State::Edit {
literal,
variant: None,
lang,
is_caption_set: false,
})
@ -494,6 +497,7 @@ async fn edit_msg_cmd_handler(
dialogue
.update(State::Edit {
literal,
variant: None,
lang,
is_caption_set: false,
})
@ -519,7 +523,7 @@ async fn edit_msg_handler(
bot: Bot,
mut db: DB,
dialogue: BotDialogue,
(literal, lang, is_caption_set): (String, String, bool),
(literal, variant, lang, is_caption_set): (String, Option<String>, String, bool),
msg: Message,
) -> BotResult<()> {
use teloxide::utils::render::Renderer;
@ -533,6 +537,28 @@ async fn edit_msg_handler(
return Ok(());
};
if let Some(variant) = variant {
if let MediaKind::Text(text) = msg.media_kind {
let html_text = Renderer::new(&text.text, &text.entities).as_html();
db.set_literal_alternative(&literal, &variant, &html_text)
.await?;
bot.send_message(chat_id, "Updated text of variant!")
.await?;
dialogue.exit().await?;
return Ok(());
} else {
bot.send_message(
chat_id,
"On variants only text alternating supported. Try to send text only",
)
.await?;
return Ok(());
}
};
match msg.media_kind {
MediaKind::Text(text) => {
db.drop_media(&literal).await?;
@ -584,6 +610,7 @@ async fn edit_msg_handler(
dialogue
.update(State::Edit {
literal,
variant: None,
lang,
is_caption_set: true,
})
@ -632,6 +659,7 @@ async fn edit_msg_handler(
dialogue
.update(State::Edit {
literal,
variant: None,
lang,
is_caption_set: true,
})
@ -707,12 +735,17 @@ async fn user_command_handler(
if !meta.is_empty() {
user.insert_meta(&mut db, &meta).await?;
}
let variant = match meta.as_str() {
"" => None,
variant => Some(variant),
};
let mut db2 = db.clone();
answer_message(
answer_message_varianted(
&bot,
msg.chat.id.0,
&mut db,
"start",
variant,
Some(make_start_buttons(&mut db2).await?),
)
.await?;
@ -733,10 +766,35 @@ async fn answer_message<RM: Into<ReplyMarkup>>(
literal: &str,
keyboard: Option<RM>,
) -> BotResult<()> {
let text = db
.get_literal_value(literal)
.await?
.unwrap_or("Please, set content of this message".into());
answer_message_varianted(bot, chat_id, db, literal, None, keyboard).await
}
async fn answer_message_varianted<RM: Into<ReplyMarkup>>(
bot: &Bot,
chat_id: i64,
db: &mut DB,
literal: &str,
variant: Option<&str>,
keyboard: Option<RM>,
) -> BotResult<()> {
let variant = match variant {
Some(variant) => {
let value = db.get_literal_alternative_value(literal, variant).await?;
if value.is_none() {
notify_admin(&format!("variant {variant} for literal {literal} is not found! falling back to just literal")).await;
}
value
}
None => None,
};
let text = match variant {
Some(text) => text,
None => db
.get_literal_value(literal)
.await?
.unwrap_or("Please, set content of this message".into()),
};
let media = db.get_media(literal).await?;
let (chat_id, msg_id) = match media.len() {
// just a text