1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-28 22:14:19 +00:00

Allow /help to be used to get info about a specific command

Also tweaks other commands to be read and handle exceptions correctly
This commit is contained in:
Steffo 2024-07-08 05:44:56 +02:00
parent a916cf0e33
commit 8f6d0a1511
Signed by: steffo
GPG key ID: 5ADA3868646C3FC0
5 changed files with 111 additions and 26 deletions

View file

@ -5,7 +5,7 @@ use teloxide::requests::Requester;
use teloxide::types::{Message}; use teloxide::types::{Message};
use super::{CommandResult}; use super::{CommandResult};
pub async fn handler(bot: Bot, message: Message, text: String) -> CommandResult { pub async fn handler(bot: &Bot, message: &Message, text: &str) -> CommandResult {
let text = format!( let text = format!(
"💬 {text}" "💬 {text}"
); );
@ -14,7 +14,7 @@ pub async fn handler(bot: Bot, message: Message, text: String) -> CommandResult
.send_message(message.chat.id, text) .send_message(message.chat.id, text)
.reply_to_message_id(message.id) .reply_to_message_id(message.id)
.await .await
.context("Failed to send message")?; .context("Non è stato possibile inviare la risposta.")?;
Ok(()) Ok(())
} }

View file

@ -187,11 +187,11 @@ impl Hash for FortuneKey {
} }
} }
pub async fn handler(bot: Bot, message: Message) -> CommandResult { pub async fn handler(bot: &Bot, message: &Message) -> CommandResult {
let today = chrono::Local::now().date_naive(); let today = chrono::Local::now().date_naive();
let author = message.from() let author = message.from()
.context("Failed to get the user who sent the original message")?; .context("Non è stato possibile determinare chi ha inviato questo comando.")?;
let author_id = author.id; let author_id = author.id;
let key = FortuneKey {today, author_id}; let key = FortuneKey {today, author_id};
@ -206,20 +206,20 @@ pub async fn handler(bot: Bot, message: Message) -> CommandResult {
.collect::<Vec<u8>>() .collect::<Vec<u8>>()
.try_into(); .try_into();
if hash.is_err() { if hash.is_err() {
anyhow::bail!("Failed to select random seed"); anyhow::bail!("Non è stato possibile determinare il tuo oroscopo.");
} }
let hash = hash.unwrap(); let hash = hash.unwrap();
let mut rng = rand::rngs::SmallRng::from_seed(hash); let mut rng = rand::rngs::SmallRng::from_seed(hash);
let fortune = FORTUNES.choose(&mut rng) let fortune = FORTUNES.choose(&mut rng)
.context("Failed to choose a fortune")?; .context("Non è stato possibile selezionare il tuo oroscopo.")?;
let _reply = bot let _reply = bot
.send_message(message.chat.id, fortune.to_string()) .send_message(message.chat.id, fortune.to_string())
.reply_to_message_id(message.id) .reply_to_message_id(message.id)
.await .await
.context("Failed to send message")?; .context("Non è stato possibile inviare la risposta.")?;
Ok(()) Ok(())
} }

View file

@ -2,11 +2,11 @@ use anyhow::Context;
use teloxide::Bot; use teloxide::Bot;
use teloxide::payloads::SendMessageSetters; use teloxide::payloads::SendMessageSetters;
use teloxide::requests::Requester; use teloxide::requests::Requester;
use teloxide::types::{Message}; use teloxide::types::{BotCommand, Message};
use teloxide::utils::command::BotCommands; use teloxide::utils::command::BotCommands;
use super::{CommandResult}; use super::{CommandResult};
pub async fn handler(bot: Bot, message: Message) -> CommandResult { pub async fn handler_all(bot: &Bot, message: &Message) -> CommandResult {
let descriptions = super::Command::descriptions().to_string(); let descriptions = super::Command::descriptions().to_string();
let text = format!("❓ Sono disponibili i seguenti comandi:\n\n{descriptions}"); let text = format!("❓ Sono disponibili i seguenti comandi:\n\n{descriptions}");
@ -15,7 +15,55 @@ pub async fn handler(bot: Bot, message: Message) -> CommandResult {
.send_message(message.chat.id, text) .send_message(message.chat.id, text)
.reply_to_message_id(message.id) .reply_to_message_id(message.id)
.await .await
.context("Failed to send message")?; .context("Non è stato possibile inviare la risposta.")?;
Ok(())
}
pub async fn handler_specific(bot: &Bot, message: &Message, target: &str) -> CommandResult {
let me = bot
.get_me()
.await
.context("Non è stato possibile recuperare informazioni sul bot.")?;
let me_username = me.username.as_ref()
.context("Non è stato possibile determinare l'username del bot.")?;
let suffix = format!("@{me_username}");
let target = target.strip_prefix("/")
.unwrap_or_else(|| target);
let target = target.strip_suffix(&suffix)
.unwrap_or_else(|| target);
log::trace!("Stripped target command: {target:?}");
let all_commands: Vec<BotCommand> = super::Command::bot_commands();
log::trace!("All commands are: {all_commands:?}");
let identify_command = |cmd: &&BotCommand| -> bool {
let command = &cmd.command;
let command = command.strip_prefix("/")
.unwrap_or_else(|| command);
target == command
};
let target = match all_commands.iter().find(identify_command) {
Some(bot_command) => bot_command,
None => anyhow::bail!("Non è stato possibile trovare il comando specificato."),
};
let text = format!("❓ Il comando {}{}:\n\n{}", target.command, suffix, target.description);
let _reply = bot
.send_message(message.chat.id, text)
.reply_to_message_id(message.id)
.await
.context("Non è stato possibile inviare la risposta.")?;
Ok(()) Ok(())
} }

View file

@ -7,7 +7,7 @@ use teloxide::dispatching::{DefaultKey, Dispatcher, HandlerExt, UpdateFilterExt}
use teloxide::dptree::entry; use teloxide::dptree::entry;
use teloxide::payloads::SendMessageSetters; use teloxide::payloads::SendMessageSetters;
use teloxide::requests::Requester; use teloxide::requests::Requester;
use teloxide::types::{Message, Update}; use teloxide::types::{ChatId, Message, MessageId, Update};
use teloxide::utils::command::BotCommands; use teloxide::utils::command::BotCommands;
mod start; mod start;
@ -15,13 +15,13 @@ mod fortune;
mod echo; mod echo;
mod help; mod help;
#[derive(Debug, Clone, BotCommands)] #[derive(Debug, Clone, PartialEq, Eq, BotCommands)]
#[command(rename_rule = "lowercase")] #[command(rename_rule = "lowercase")]
pub(self) enum Command { pub(self) enum Command {
#[command(description = "Invia messaggio di introduzione.")] #[command(description = "Invia messaggio di introduzione.")]
Start, Start,
#[command(description = "Visualizza l'elenco dei comandi disponibili.")] #[command(description = "Visualizza l'elenco dei comandi disponibili, o mostra informazioni su uno specifico comando.")]
Help, Help(String),
#[command(description = "Mostra il tuo oroscopo di oggi.")] #[command(description = "Mostra il tuo oroscopo di oggi.")]
Fortune, Fortune,
#[command(description = "Ripeti il testo inviato.")] #[command(description = "Ripeti il testo inviato.")]
@ -31,21 +31,58 @@ pub(self) enum Command {
async fn handle_command(bot: Bot, command: Command, message: Message) -> CommandResult { async fn handle_command(bot: Bot, command: Command, message: Message) -> CommandResult {
log::trace!("Received command: {command:?}"); log::trace!("Received command: {command:?}");
match command { let result = match command {
Command::Start => start::handler(bot, message).await, Command::Start => start::handler(&bot, &message).await,
Command::Help => help::handler(bot, message).await, Command::Help(target) => match target.as_str() {
Command::Fortune => fortune::handler(bot, message).await, "" => help::handler_all(&bot, &message).await,
Command::Echo(text) => echo::handler(bot, message, text).await, _ => help::handler_specific(&bot, &message, &target).await,
},
Command::Fortune => fortune::handler(&bot, &message).await,
Command::Echo(text) => echo::handler(&bot, &message, &text).await,
};
if result.is_ok() {
return Ok(())
} }
let chat_id = message.chat.id;
let message_id = message.id;
let error = result.unwrap_err();
let result2 = error_command(&bot, chat_id, message_id, &error).await;
if result2.is_ok() {
return Ok(())
}
let error2 = result2.unwrap_err();
log::error!("Command message {message_id:?} in {chat_id:?} errored out with `{error}`, and it was impossible to handle the error because of `{error2}`\n\n{error2:?}");
Ok(())
}
async fn error_command(bot: &Bot, chat_id: ChatId, message_id: MessageId, error: &Error) -> CommandResult {
log::debug!("Command message {message_id:?} in {chat_id:?} errored out with `{error}`");
let text = format!("⚠️ {}", error.to_string());
let _reply = bot
.send_message(chat_id, text)
.reply_to_message_id(message_id)
.await
.context("Non è stato possibile inviare la risposta.")?;
Ok(())
} }
async fn unknown_command(bot: Bot, message: Message) -> CommandResult { async fn unknown_command(bot: Bot, message: Message) -> CommandResult {
log::trace!("Received an unknown command."); log::debug!("Received an unknown command.");
bot.send_message(message.chat.id, "⚠️ Comando sconosciuto.") bot.send_message(message.chat.id, "⚠️ Comando sconosciuto.")
.reply_to_message_id(message.id) .reply_to_message_id(message.id)
.await .await
.context("Failed to send message")?; .context("Non è stato possibile inviare la risposta.")?;
Ok(()) Ok(())
} }

View file

@ -5,9 +5,9 @@ use teloxide::requests::Requester;
use teloxide::types::{Message}; use teloxide::types::{Message};
use super::{CommandResult}; use super::{CommandResult};
pub async fn handler(bot: Bot, message: Message) -> CommandResult { pub async fn handler(bot: &Bot, message: &Message) -> CommandResult {
let author = message.from() let author = message.from()
.context("Failed to get the user who sent the original message")?; .context("Non è stato possibile determinare chi ha inviato questo comando.")?;
let author_username = match author.username.as_ref() { let author_username = match author.username.as_ref() {
None => { None => {
@ -21,10 +21,10 @@ pub async fn handler(bot: Bot, message: Message) -> CommandResult {
let me = bot let me = bot
.get_me() .get_me()
.await .await
.context("Failed to get information about self")?; .context("Non è stato possibile recuperare informazioni sul bot.")?;
let me_username = me.username.as_ref() let me_username = me.username.as_ref()
.context("Failed to get bot's username")?; .context("Non è stato possibile determinare l'username del bot.")?;
let text = format!( let text = format!(
"👋 Ciao {author_username}! Sono @{me_username}, il robot tuttofare della RYG!\n\n\ "👋 Ciao {author_username}! Sono @{me_username}, il robot tuttofare della RYG!\n\n\
@ -36,7 +36,7 @@ pub async fn handler(bot: Bot, message: Message) -> CommandResult {
.send_message(message.chat.id, text) .send_message(message.chat.id, text)
.reply_to_message_id(message.id) .reply_to_message_id(message.id)
.await .await
.context("Failed to send message")?; .context("Non è stato possibile inviare la risposta.")?;
Ok(()) Ok(())
} }