From 22025cde110eb6c3ee21b39ab72e53b1cd5a8ac9 Mon Sep 17 00:00:00 2001 From: Akulij Date: Sat, 31 May 2025 10:35:52 +0500 Subject: [PATCH] handle callbacks in script_handler --- src/bot_handler.rs | 114 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 98 insertions(+), 16 deletions(-) diff --git a/src/bot_handler.rs b/src/bot_handler.rs index f8e8355..1b9e7bc 100644 --- a/src/bot_handler.rs +++ b/src/bot_handler.rs @@ -4,10 +4,10 @@ use std::{ sync::{Arc, RwLock}, }; use teloxide::{ - dispatching::UpdateFilterExt, + dispatching::{dialogue::GetChatId, UpdateFilterExt}, dptree::{self, Handler}, prelude::DependencyMap, - types::{InlineKeyboardButton, InlineKeyboardMarkup, Message, Update}, + types::{CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup, Message, Update}, Bot, }; @@ -16,28 +16,42 @@ use crate::{ commands::BotCommand, db::{CallDB, DB}, message_answerer::MessageAnswerer, - update_user_tg, BotResult, + update_user_tg, BotError, BotResult, }; pub type BotHandler = Handler<'static, DependencyMap, BotResult<()>, teloxide::dispatching::DpHandlerDescription>; pub fn script_handler(rc: Arc>) -> BotHandler { - dptree::entry().branch( - Update::filter_message() - // check if message is command - .filter_map(|m: Message| m.text().and_then(|t| BotCommand::from_str(t).ok())) - // check if command is presented in config - .filter_map(move |bc: BotCommand| { - let rc = std::sync::Arc::clone(&rc); - let command = bc.command(); + let crc = rc.clone(); + dptree::entry() + .branch( + Update::filter_message() + // check if message is command + .filter_map(|m: Message| m.text().and_then(|t| BotCommand::from_str(t).ok())) + // check if command is presented in config + .filter_map(move |bc: BotCommand| { + let rc = std::sync::Arc::clone(&rc); + let command = bc.command(); - let rc = rc.read().expect("RwLock lock on commands map failed"); + let rc = rc.read().expect("RwLock lock on commands map failed"); - rc.get_command_message(command) - }) - .endpoint(handle_botmessage), - ) + rc.get_command_message(command) + }) + .endpoint(handle_botmessage), + ) + .branch( + Update::filter_callback_query() + .filter_map(move |q: CallbackQuery| { + q.data.and_then(|data| { + let rc = std::sync::Arc::clone(&crc); + let rc = rc.read().expect("RwLock lock on commands map failed"); + + rc.get_callback_message(&data) + }) + }) + .endpoint(handle_callback), + ) } async fn handle_botmessage(bot: Bot, mut db: DB, bm: BotMessage, msg: Message) -> BotResult<()> { @@ -78,3 +92,71 @@ async fn handle_botmessage(bot: Bot, mut db: DB, bm: BotMessage, msg: Message) - Ok(()) } + +async fn handle_callback(bot: Bot, mut db: DB, bm: BotMessage, q: CallbackQuery) -> BotResult<()> { + info!("Eval BM: {:?}", bm); + let tguser = q.from.clone(); + let user = db + .get_or_init_user(tguser.id.0 as i64, &tguser.first_name) + .await?; + let user = update_user_tg(user, &tguser); + user.update_user(&mut db).await?; + + let buttons = bm + .resolve_buttons(&mut db) + .await? + .map(|buttons| InlineKeyboardMarkup { + inline_keyboard: buttons + .iter() + .map(|r| { + r.iter() + .map(|b| match b { + botscript::ButtonLayout::Callback { + name, + literal: _, + callback, + } => InlineKeyboardButton::callback(name, callback), + }) + .collect() + }) + .collect(), + }); + let literal = bm.literal().map_or("", |s| s.as_str()); + + let (chat_id, msg_id) = { + let chat_id = match q.chat_id() { + Some(chat_id) => chat_id.0, + None => tguser.id.0 as i64, + }; + + let msg_id = q.message.map_or_else( + || { + Err(BotError::MsgTooOld( + "Failed to get message id, probably message too old".to_string(), + )) + }, + |m| Ok(m.id().0), + ); + + (chat_id, msg_id) + }; + + let ma = MessageAnswerer::new(&bot, &mut db, chat_id); + match bm.is_replace() { + true => { + match msg_id { + Ok(msg_id) => { + ma.replace_message(msg_id, literal, buttons).await?; + } + Err(err) => { + ma.answer(literal, None, buttons).await?; + } + }; + } + false => { + ma.answer(literal, None, buttons).await?; + } + } + + Ok(()) +}