diff --git a/src/cmd_carte.rs b/src/cmd_carte.rs new file mode 100644 index 0000000..4bbcf33 --- /dev/null +++ b/src/cmd_carte.rs @@ -0,0 +1,125 @@ +use teloxide::{ + dispatching::dialogue::{GetChatId, InMemStorage}, + payloads::SendMessageSetters, + prelude::Dialogue, + requests::Requester, + types::{ + CallbackQuery, ChatId, InlineKeyboardButton, InlineKeyboardMarkup, Message, MessageId, ReplyMarkup + }, + Bot, +}; + +use crate::HandlerResult; + +#[derive(Default, Clone, Debug)] +pub enum CardState { + #[default] + Start, + ChooseCardOption, + GiveCard { + /// ID of the message querying the target of the /carte. + /// Used to delete the message after the selection. + message_id: MessageId, + }, + // ReturnCard { + // /// ID of the message. + // /// Used to delete the message after the selection. + // message_id: MessageId, + // }, +} +pub type CarteDialogue = Dialogue>; + + +// when /carte: message with where the card is (either in office, either in CLIC or the name of the holder) +// if in CLIC, propose to give the card, or to do nothing +// if a holder have the card, propose to give back the card to the office or do nothing + + +/// Starts the /carte dialogue. +pub async fn start_card_dialogue( + bot: Bot, + msg: Message, + dialogue: CarteDialogue, +) -> HandlerResult { + log::info!("Starting /carte dialogue"); + + // log::debug!("Removing /carte message"); + // bot.delete_message(msg.chat.id, msg.id).await?; + + // if there is a holder: + let cartd_status = "CLIC"; // TODO get DB info from who hold the card + + let is_at_office = cartd_status == "CLIC"; + let (text, token) = if is_at_office {("Donner la carte", "give_card")} else {("Rendre la carte", "return_card")}; + + let row = vec![ + InlineKeyboardButton::callback(text, token), + InlineKeyboardButton::callback("Cancel", "nothing") + ]; + + log::debug!("Sending message with inline keyboard for callback"); + + bot + .send_message(msg.chat.id, cartd_status) + .reply_markup(ReplyMarkup::InlineKeyboard(InlineKeyboardMarkup::new(vec![row]))) + .await?; + + log::debug!("Updating dialogue to ChooseTarget"); + dialogue + .update(CardState::ChooseCardOption) + .await?; + + Ok(()) +} + + +/// Handles the callback from the inline keyboard, and sends a message to confirm selection of option. +/// The CallbackQuery data contains the action to perform. +pub async fn choose_option( + bot: Bot, + callback_query: CallbackQuery, + dialogue: CarteDialogue, + message_id: MessageId, +) -> HandlerResult { + if let Some(id) = callback_query.chat_id() { + + log::debug!("Removing option query message"); + bot.delete_message(dialogue.chat_id(), message_id).await?; + + log::debug!("Sending target selection message"); + + return match callback_query.data.unwrap_or_default().as_str() { + "give_card" => { + + let msg = bot.send_message(id, "Qui prend la carte ?").await?; + dialogue.update(CardState::GiveCard { message_id: msg.id }).await?; + Ok(()) + }, + "return_card" => return_card(bot, id).await, + _ => Ok(()), // TODO close the dialogue + } + } + + Ok(()) +} + + +pub async fn give_card( + bot: Bot, + msg: Message, + dialogue: CarteDialogue +) -> HandlerResult { + + let card_holder = msg.text(); + + // TODO set holder in the db + bot.send_message(dialogue.chat_id(), "{} est désormais en posséssion de la carte invité").await?; + + + Ok(()) +} + +async fn return_card(bot: Bot, chat_id: ChatId) -> HandlerResult { + bot.send_message(chat_id, "{} a rendu la carte au bureau !").await?; + Ok(()) // TODO change state in the db to bureau +} \ No newline at end of file diff --git a/src/commands.rs b/src/commands.rs index bba635b..13b3e10 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -12,15 +12,12 @@ use teloxide::{ use crate::{ cmd_authentication::{ admin_list, admin_remove, authenticate, authorizations, authorize, unauthorize - }, - cmd_bureau::bureau, - cmd_poll::{ + }, cmd_bureau::bureau, cmd_carte::{choose_option, give_card, start_card_dialogue, CardState}, cmd_poll::{ choose_target, set_quote, start_poll_dialogue, stats, PollState - }, - HandlerResult + }, HandlerResult }; pub fn command_message_handler( @@ -35,7 +32,8 @@ pub fn command_message_handler( require_authorization() .branch(dptree::case![Command::Bureau].endpoint(bureau)) .branch(dptree::case![Command::Poll].endpoint(start_poll_dialogue)) - .branch(dptree::case![Command::Stats].endpoint(stats)), + .branch(dptree::case![Command::Stats].endpoint(stats)) + .branch(dptree::case![Command::Carte].endpoint(start_card_dialogue)), ) .branch( require_admin().chain( @@ -55,11 +53,15 @@ pub fn command_message_handler( ), ) .branch(dptree::case![PollState::SetQuote { message_id, target }].endpoint(set_quote)) + .branch(dptree::case![CardState::GiveCard { message_id }].endpoint(give_card)) + } pub fn command_callback_query_handler( ) -> Endpoint<'static, DependencyMap, HandlerResult, DpHandlerDescription> { - dptree::case![PollState::ChooseTarget { message_id }].endpoint(choose_target) + dptree::entry() + .branch(dptree::case![PollState::ChooseTarget { message_id }].endpoint(choose_target)) + .branch(dptree::case![CardState::ChooseCardOption].endpoint(choose_option)) } // ----------------------------- ACCESS CONTROL ------------------------------- @@ -147,6 +149,8 @@ pub enum Command { Authorizations, #[command(description = "(Admin) Affiche les stats des membres du comité")] Stats, + #[command(description = "Traque la carte invité CLIC")] + Carte } impl Command { @@ -163,6 +167,7 @@ impl Command { Self::Unauthorize(..) => "unauthorize", Self::Authorizations => "authorizations", Self::Stats => "stats", + Self::Carte => "carte", } } } diff --git a/src/main.rs b/src/main.rs index b63db1b..681bb1e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ mod directus; mod cmd_poll; mod cmd_bureau; mod cmd_authentication; +mod cmd_carte; pub type HandlerResult = Result<(), Box>;