From 4b6053fc8fa9d01f1679f6f373bb77432113da40 Mon Sep 17 00:00:00 2001 From: Lucien Cartier-Tilet Date: Tue, 2 Sep 2025 15:18:01 +0200 Subject: [PATCH] feat: add roll slash command --- src/discord/mod.rs | 6 +++- src/discord/roll.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 1 + 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/discord/roll.rs diff --git a/src/discord/mod.rs b/src/discord/mod.rs index 82196de..532bf97 100644 --- a/src/discord/mod.rs +++ b/src/discord/mod.rs @@ -2,6 +2,10 @@ use color_eyre::eyre::{Error, Result}; use poise::serenity_prelude::{self as serenity, FullEvent}; use tracing::info; +mod roll; + +type Context<'a> = poise::Context<'a, (), Error>; + fn event_handler(_ctx: serenity::Context, event: &FullEvent) { if let FullEvent::Ready { data_about_bot } = event { info!("Logged in as {}", data_about_bot.user.name); @@ -13,7 +17,7 @@ pub async fn make_bot() -> Result { let intents = serenity::GatewayIntents::non_privileged(); let framework = poise::Framework::<(), Error>::builder() .options(poise::FrameworkOptions { - commands: vec![], + commands: vec![roll::roll()], event_handler: |ctx, event, _framework: poise::FrameworkContext<'_, (), _>, _data| { Box::pin(async move { event_handler(ctx.clone(), event); diff --git a/src/discord/roll.rs b/src/discord/roll.rs new file mode 100644 index 0000000..4a2a145 --- /dev/null +++ b/src/discord/roll.rs @@ -0,0 +1,70 @@ +use std::str::FromStr; + +use super::Context; +use color_eyre::eyre::{Error, Result}; +use tracing::info; + +enum Advantage { + None, + Beni, + Maudit, +} + +impl FromStr for Advantage { + type Err = color_eyre::eyre::Report; + + fn from_str(s: &str) -> std::result::Result { + match s { + "aucun" => Ok(Self::None), + "béni" => Ok(Self::Beni), + "maudit" => Ok(Self::Maudit), + other => Err(Error::msg(format!("Could not parse {other} into an Advantage enum"))), + } + } +} + +impl TryFrom> for Advantage { + type Error = color_eyre::eyre::Report; + + fn try_from(value: Option) -> std::result::Result { + match value { + Some(str) => Advantage::from_str(&str), + None => Ok(Advantage::None) + } + } +} + + +impl std::fmt::Display for Advantage { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let str = match self { + Self::None => "aucun".to_string(), + Self::Beni => "béni".to_string(), + Self::Maudit => "maudit".to_string(), + }; + write!(f, "{str}") + } +} + +async fn advantage_autocomplete(_ctx: Context<'_>, _: &str) -> impl Iterator { + [Advantage::None, Advantage::Beni, Advantage::Maudit] + .iter() + .map(std::string::ToString::to_string) + .collect::>() + .into_iter() +} + +#[poise::command(slash_command)] +pub async fn roll( + ctx: Context<'_>, + #[description = "Seuil de réussite"] sr: u32, + #[description = "Maîtrise"] mastery: u32, + #[description = "Avantage"] + #[autocomplete = "advantage_autocomplete"] + advantage: Option, +) -> Result<()> { + info!("Called /roll with following context: {ctx:?}"); + let advantage = Advantage::try_from(advantage)?; + info!("Rolling against SR {sr} with mastery {mastery} and advantage {advantage}"); + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 34fabdd..63f4d8c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ #![deny(clippy::all, clippy::pedantic, clippy::nursery)] #![warn(missing_docs)] #![allow(clippy::module_name_repetitions, clippy::redundant_pub_crate)] +#![allow(clippy::unused_async)] mod discord; mod utils;