Updated roll to notify a user
This commit is contained in:
@@ -1,34 +1,33 @@
|
|||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use serenity::all::{
|
use serenity::all::{
|
||||||
CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption,
|
CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption, Mentionable, UserId
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::bot::commands::{create_response, create_dm, edit_response};
|
use crate::bot::commands::{create_response, edit_response, user_id_dm};
|
||||||
|
|
||||||
pub async fn run(ctx: &Context, command: &CommandInteraction) {
|
pub async fn run(ctx: &Context, command: &CommandInteraction) {
|
||||||
let hidden = match command.data.options.get(1) {
|
// Check if the roll result is private
|
||||||
Some(o) => match o.value.as_bool() {
|
let private = command.data.options.iter().find(|opt| opt.name == "private")
|
||||||
Some(b) => b,
|
.and_then(|o| o.value.as_bool())
|
||||||
None => false,
|
.unwrap_or(true);
|
||||||
},
|
|
||||||
None => false,
|
// Retrieve the DM's name or ID from the options (optional)
|
||||||
};
|
let user = command.data.options.iter().find(|opt| opt.name == "user")
|
||||||
create_response(&ctx, &command, format!("Rolling..."), hidden).await;
|
.and_then(|o| o.value.as_mentionable());
|
||||||
let dice_string = match command.data.options.get(0) {
|
|
||||||
Some(o) => match o.value.as_str() {
|
create_response(&ctx, &command, format!("Rolling..."), private).await;
|
||||||
Some(s) => s.split_whitespace().collect::<String>(),
|
|
||||||
|
let dice_string = match command.data.options.get(0)
|
||||||
|
.and_then(|o| o.value.as_str())
|
||||||
|
.map(|s| s.split_whitespace().collect::<String>()) {
|
||||||
|
Some(dice_value) => dice_value,
|
||||||
None => {
|
None => {
|
||||||
log::warn!("Missing dice option");
|
log::warn!("Missing or invalid dice option");
|
||||||
edit_response(&ctx, &command, format!("Dice option is missing")).await;
|
let _ = edit_response(&ctx, &command, "Dice option is missing".to_string()).await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
None => {
|
|
||||||
log::warn!("Missing dice option");
|
|
||||||
edit_response(&ctx, &command, format!("Dice option is missing")).await;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let dice = parse_dice(dice_string.as_str());
|
let dice = parse_dice(dice_string.as_str());
|
||||||
match dice {
|
match dice {
|
||||||
Ok((count, sides, modifier)) => {
|
Ok((count, sides, modifier)) => {
|
||||||
@@ -52,7 +51,15 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) {
|
|||||||
"".to_string()
|
"".to_string()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
edit_response(&ctx, &command, response).await;
|
|
||||||
|
match user {
|
||||||
|
Some(id) => {
|
||||||
|
let user_id = UserId::new(id.get());
|
||||||
|
user_id_dm(&ctx, &user_id, format!("Dice roll from {}: {}", &command.user.mention(), response)).await;
|
||||||
|
edit_response(&ctx, command, format!("Sending dice roll results to {}", &user_id.mention())).await;
|
||||||
|
},
|
||||||
|
None => edit_response(&ctx, &command, response).await
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Err(why) => {
|
Err(why) => {
|
||||||
edit_response(&ctx, &command, format!("Invalid dice string: {}", why)).await;
|
edit_response(&ctx, &command, format!("Invalid dice string: {}", why)).await;
|
||||||
@@ -61,64 +68,72 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_dice(dice: &str) -> Result<(u32, u32, i32), String> {
|
fn parse_dice(dice: &str) -> Result<(u32, u32, i32), String> {
|
||||||
let mut parts = dice.split("d");
|
// If the input is just a number (e.g., "20" or "6"), assume it's the number of sides
|
||||||
let count = match parts.next() {
|
if let Ok(n) = dice.parse::<u32>() {
|
||||||
Some(c) => match c.parse::<u32>() {
|
return Ok((1, n, 0)); // Assume 1 dice with 0 modifiers
|
||||||
Ok(n) => n,
|
}
|
||||||
Err(_) => return Err(format!("Invalid dice count: {}", c)),
|
|
||||||
},
|
// If the input starts with "d", assume it's shorthand for "1dX"
|
||||||
None => return Err(format!("Invalid dice string: {}", dice)),
|
let dice = if dice.starts_with("d") {
|
||||||
|
format!("1{}", dice) // Prepend "1"
|
||||||
|
} else {
|
||||||
|
dice.to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut parts = dice.split(['d', '+', '-'].as_ref());
|
||||||
let mut positive_modifier = true;
|
let mut positive_modifier = true;
|
||||||
let mut parts = match parts.next() {
|
|
||||||
Some(p) => {
|
// Parse the dice count
|
||||||
// Check if contains a +/- modifier
|
let count = match parts.next() {
|
||||||
if p.contains("+") {
|
Some("") => 1, // Handle cases like "d6", assume 1 dice
|
||||||
positive_modifier = true;
|
Some(c) => match c.parse::<u32>() {
|
||||||
p.split("+")
|
Ok(n) => n,
|
||||||
} else if p.contains("-") {
|
Err(_) => return Err(format!("Invalid dice count: {}", c)),
|
||||||
positive_modifier = false;
|
|
||||||
p.split("-")
|
|
||||||
} else {
|
|
||||||
p.split("+")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => return Err(format!("Invalid dice string: {}", dice)),
|
|
||||||
};
|
|
||||||
let sides = match parts.next() {
|
|
||||||
Some(s) => match s.parse::<u32>() {
|
|
||||||
Ok(n) => {
|
|
||||||
if n == 4 || n == 6 || n == 8 || n == 10 || n == 12 || n == 20 || n == 100 {
|
|
||||||
n
|
|
||||||
} else {
|
|
||||||
return Err(format!(
|
|
||||||
"Expected one of d4, d6, d8, d10, d12, d20, d100 but received d{}",
|
|
||||||
s
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
return Err(format!(
|
|
||||||
"Expected one of d4, d6, d8, d10, d12, d20, d100 but received d{}",
|
|
||||||
s
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
None => return Err(format!("Invalid dice string: {}", dice)),
|
None => return Err(format!("Invalid dice string: {}", dice)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Parse the number of sides
|
||||||
|
let sides_part = parts.next().ok_or_else(|| format!("Invalid dice string: {}", dice))?;
|
||||||
|
let sides = match sides_part.parse::<u32>() {
|
||||||
|
Ok(n) => {
|
||||||
|
if [4, 6, 8, 10, 12, 20, 100].contains(&n) {
|
||||||
|
n
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"Expected one of d4, d6, d8, d10, d12, d20, d100 but received d{}",
|
||||||
|
n
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => return Err(format!(
|
||||||
|
"Expected one of d4, d6, d8, d10, d12, d20, d100 but received d{}",
|
||||||
|
sides_part
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Determine if there's a modifier (+ or -)
|
||||||
|
if dice.contains('+') {
|
||||||
|
positive_modifier = true;
|
||||||
|
} else if dice.contains('-') {
|
||||||
|
positive_modifier = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the modifier, if present
|
||||||
let modifier = match parts.next() {
|
let modifier = match parts.next() {
|
||||||
Some(m) => match m.parse::<i32>() {
|
Some(m) => match m.parse::<i32>() {
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
if positive_modifier {
|
if positive_modifier {
|
||||||
n
|
n
|
||||||
} else {
|
} else {
|
||||||
n * -1
|
-n
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(_) => return Err(format!("Invalid dice modifier: {}", m)),
|
||||||
Err(_) => return Err(format!("Invalid dice modifier: {}", m)),
|
|
||||||
},
|
},
|
||||||
None => 0,
|
None => 0, // No modifier found
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok((count, sides, modifier))
|
Ok((count, sides, modifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,9 +146,13 @@ pub fn register() -> CreateCommand {
|
|||||||
.add_option(
|
.add_option(
|
||||||
CreateCommandOption::new(
|
CreateCommandOption::new(
|
||||||
CommandOptionType::Boolean,
|
CommandOptionType::Boolean,
|
||||||
"hidden",
|
"private",
|
||||||
"Whether the roll should be hidden",
|
"Make the roll private (Default: True)",
|
||||||
)
|
)
|
||||||
.required(false),
|
.required(false),
|
||||||
)
|
)
|
||||||
|
.add_option(
|
||||||
|
CreateCommandOption::new(CommandOptionType::Mentionable, "user", "User to receive the roll results")
|
||||||
|
.required(false),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use serenity::prelude::*;
|
use serenity::prelude::*;
|
||||||
use serenity::all::{
|
use serenity::all::{
|
||||||
CommandInteraction, CreateInteractionResponse, CreateInteractionResponseMessage, CreateMessage,
|
CommandInteraction, CreateInteractionResponse, CreateInteractionResponseMessage, CreateMessage, EditInteractionResponse, InteractionResponseFlags, Message, User, UserId
|
||||||
EditInteractionResponse, InteractionResponseFlags, Message,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod audio;
|
pub mod audio;
|
||||||
@@ -14,13 +13,28 @@ pub async fn process_message(ctx: &Context, command: &CommandInteraction, privat
|
|||||||
create_response(&ctx, &command, format!("Processing..."), private).await;
|
create_response(&ctx, &command, format!("Processing..."), private).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_dm(
|
pub async fn user_id_dm(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
command: &CommandInteraction,
|
user_id: &UserId,
|
||||||
content: String,
|
content: String,
|
||||||
) -> Option<Message> {
|
) -> Option<Message> {
|
||||||
let data = CreateMessage::new().content(content.to_owned());
|
let data = CreateMessage::new().content(content.to_owned());
|
||||||
return match command.user.direct_message(ctx, data).await {
|
return match user_id.dm(ctx, data).await {
|
||||||
|
Ok(message) => Some(message),
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("Failed to create direct message for {content}\n{err}");
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn user_dm(
|
||||||
|
ctx: &Context,
|
||||||
|
user: &User,
|
||||||
|
content: String,
|
||||||
|
) -> Option<Message> {
|
||||||
|
let data = CreateMessage::new().content(content.to_owned());
|
||||||
|
return match user.direct_message(ctx, data).await {
|
||||||
Ok(message) => Some(message),
|
Ok(message) => Some(message),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("Failed to create direct message for {content}\n{err}");
|
log::error!("Failed to create direct message for {content}\n{err}");
|
||||||
|
|||||||
Reference in New Issue
Block a user