diff --git a/src/interfaces/database/models/diario.rs b/src/interfaces/database/models/diario.rs index c1ecbf8b..25fe4b39 100644 --- a/src/interfaces/database/models/diario.rs +++ b/src/interfaces/database/models/diario.rs @@ -1,5 +1,5 @@ -use diesel::{Identifiable, Insertable, Queryable, Selectable}; use diesel::pg::Pg; +use diesel::{Identifiable, Insertable, Queryable, QueryableByName, Selectable}; use crate::interfaces::database::models::users::RoyalnetUserId; use crate::newtype_sql; @@ -17,7 +17,7 @@ pub struct DiarioAddition { pub context: Option, } -#[derive(Debug, Clone, PartialEq, Identifiable, Queryable, Selectable, Insertable)] +#[derive(Debug, Clone, PartialEq, Identifiable, Queryable, Selectable, Insertable, QueryableByName)] #[diesel(table_name = diario)] #[diesel(check_for_backend(Pg))] pub struct Diario { diff --git a/src/services/telegram/commands/mod.rs b/src/services/telegram/commands/mod.rs index 000058f0..ebbb76af 100644 --- a/src/services/telegram/commands/mod.rs +++ b/src/services/telegram/commands/mod.rs @@ -26,7 +26,7 @@ pub mod cat; pub mod roll; pub mod diario; pub mod matchmaking; -mod quote; +pub mod quote; type CommandResult = AnyResult<()>; @@ -59,6 +59,8 @@ pub enum Command { Diario(diario::DiarioArgs), #[command(description = "Chiedi chi è disponibile per giocare a qualcosa.")] Matchmaking(matchmaking::MatchmakingArgs), + #[command(description = "Invia una riga dal diario RYG.")] + Quote(quote::QuoteArgs), } impl Command { @@ -107,6 +109,7 @@ impl Command { Command::Roll(ref roll) => roll::handler(&bot, &message, roll).await, Command::Diario(ref args) => diario::handler(&bot, &message, args, &database).await, Command::Matchmaking(ref args) => matchmaking::handler(&bot, &message, args, &database).await, + Command::Quote(ref id) => quote::handler(&bot, &message, id, &database).await, }; log::trace!("Delegating error handling to error handler..."); diff --git a/src/services/telegram/commands/quote.rs b/src/services/telegram/commands/quote.rs new file mode 100644 index 00000000..9b440fed --- /dev/null +++ b/src/services/telegram/commands/quote.rs @@ -0,0 +1,102 @@ +use crate::interfaces::database::models::{Diario, RoyalnetUser}; +use crate::services::telegram::commands::CommandResult; +use crate::services::telegram::dependencies::interface_database::DatabaseInterface; +use crate::utils::telegram_string::TelegramWrite; +use anyhow::Context; +use diesel::{sql_query, RunQueryDsl}; +use std::str::FromStr; +use teloxide::payloads::SendMessageSetters; +use teloxide::requests::Requester; +use teloxide::types::{Message, ParseMode, ReplyParameters}; +use teloxide::Bot; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct QuoteArgs { + id: Option, +} + +impl FromStr for QuoteArgs { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + if s.is_empty() { + Ok( + Self { + id: None + } + ) + } else { + Ok( + Self { + id: Some( + s.parse()? + ) + } + ) + } + } +} + +pub async fn handler(bot: &Bot, message: &Message, args: &QuoteArgs, database: &DatabaseInterface) -> CommandResult { + let author = message.from.as_ref() + .context("Non è stato possibile determinare chi abbia inviato il comando.")?; + + let mut database = database.connect()?; + + let _: RoyalnetUser = { + use diesel::prelude::*; + use diesel::{ExpressionMethods, QueryDsl}; + use crate::interfaces::database::schema::telegram::dsl::*; + use crate::interfaces::database::schema::users::dsl::*; + use crate::interfaces::database::models::RoyalnetUser; + + telegram + .filter(telegram_id.eq::( + author.id.0.try_into() + .context("Non è stato possibile processare il tuo ID Telegram per via di un overflow.")? + )) + .inner_join(users) + .select(RoyalnetUser::as_select()) + .get_result(&mut database) + .context("Non è stato possibile recuperare il tuo utente Telegram dal database RYG.")? + }; + + let entry = match args.id { + None => { + sql_query(include_str!("quote_random.sql")) + .load::(&mut database) + .context("Non è stato possibile recuperare una riga di diario dal database RYG.")? + .into_iter() + .next() + .context("Non è stata trovata nessuna riga di diario nel database RYG.")? + } + Some(requested_id) => { + use crate::interfaces::database::query_prelude::*; + use crate::interfaces::database::schema::diario; + + diario::table + .filter(diario::id.eq(requested_id)) + .select(Diario::as_select()) + .get_result(&mut database) + .context("Non è stato possibile recuperare la riga di diario specificata dal database RYG. Forse non esiste?")? + } + }; + + let text = format!( + "📖 Dal diario RYG...\n\ + \n\ + {}", + entry.to_string_telegram(), + ); + + let _reply = bot + .send_message(message.chat.id, text) + .parse_mode(ParseMode::Html) + .reply_parameters(ReplyParameters::new(message.id)) + .await + // teloxide does not support blockquotes yet and errors out on parsing the response + // .context("Non è stato possibile inviare la risposta.")? + ; + + Ok(()) +} \ No newline at end of file diff --git a/src/services/telegram/commands/quote_random.sql b/src/services/telegram/commands/quote_random.sql new file mode 100644 index 00000000..aeb815fc --- /dev/null +++ b/src/services/telegram/commands/quote_random.sql @@ -0,0 +1,13 @@ +SELECT id, + saver_id, + saved_on, + quoted_id, + quoted_name, + warning, + quote, + context +FROM diario + TABLESAMPLE + system_time(10) +ORDER BY RANDOM() +LIMIT 1;