use axum::http::StatusCode; use sqlx::PgPool; use twilight_interactions::command::{CommandModel, CreateCommand}; use twilight_mention::{Mention, timestamp::{TimestampStyle, Timestamp}}; use twilight_model::{id::{Id, marker::{InteractionMarker, ChannelMarker, UserMarker}}, http::interaction::{InteractionResponse, InteractionResponseType, InteractionResponseData}, channel::message::MessageFlags}; #[derive(CommandModel, CreateCommand)] #[command(name = "set_fact", desc = "Quietly save a fact")] pub struct SetFactCommand { #[command(rename = "name", desc = "Fact name")] fact_name: String, #[command(rename = "value", desc = "Fact value")] fact_value: String, } #[derive(CommandModel, CreateCommand)] #[command(name = "get_fact", desc = "Retrieve and display the value of a fact")] pub struct GetFactCommand { #[command(rename = "name", desc = "Fact name")] fact_name: String, #[command(desc = "Should it be displayed publically, by default it won't be")] public: Option, } pub async fn set_fact( interaction_id: Id, channel_id: Option>, author_id: Id, command_data: SetFactCommand, pg_pool: &PgPool, ) -> Result { let Ok(()) = crate::database::set_fact( pg_pool, interaction_id.to_string(), channel_id.map(|cid| cid.to_string()), author_id.to_string(), command_data.fact_name.to_owned(), command_data.fact_value.to_owned()).await else { return Err((StatusCode::INTERNAL_SERVER_ERROR, "Error saving fact.".to_string())); }; Ok(InteractionResponse { kind: InteractionResponseType::ChannelMessageWithSource, data: Some(InteractionResponseData { content: Some(format!( "Set {0} to {1}", command_data.fact_name, command_data.fact_value )), flags: Some(MessageFlags::EPHEMERAL), ..Default::default() }), }) } pub async fn get_fact( channel_id: Option>, author_id: Id, command_data: GetFactCommand, pg_pool: &PgPool, ) -> Result { let Ok(fact) = crate::database::get_fact( pg_pool, channel_id.map(|cid| cid.to_string()), author_id.to_string(), command_data.fact_name.to_owned(), ).await else { return Err((StatusCode::INTERNAL_SERVER_ERROR, "Error retrieving fact.".to_string())); }; let content = match fact { None => format!("Fact {0} in channel {1} by you, {2}, was not found.", command_data.fact_name, channel_id.map_or("".to_string(), |cid| cid.mention().to_string()), author_id.mention() ), Some(fact) => format!( "Fact **{0}** was set to **{1}** by {2} at {3}, and was reset {4} times in total since {5}.", command_data.fact_name, fact.value, author_id.mention(), Timestamp::new(fact.updated_at.unix_timestamp().try_into().unwrap(), Some(TimestampStyle::RelativeTime)).mention(), fact.version, Timestamp::new(fact.created_at.unix_timestamp().try_into().unwrap(), Some(TimestampStyle::ShortDateTime)).mention(), ), }; Ok(InteractionResponse { kind: InteractionResponseType::ChannelMessageWithSource, data: Some(InteractionResponseData { content: Some(content), flags: match command_data.public { Some(true) => None, _ => Some(MessageFlags::EPHEMERAL) }, ..Default::default() }), }) }