diff --git a/docker-compose.yml b/docker-compose.yml index 6245902..a34fabd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,10 +8,10 @@ name: siren services: bot: image: siren:${SIREN_VERSION:-latest} - container_name: siren + container_name: siren-bot env_file: *env environment: - DATABASE_HOST: postgres + DATABASE_HOST: siren-postgres DATABASE_PORT: 5432 REDIS_HOST: redis REDIS_PORT: 6379 @@ -29,7 +29,7 @@ services: postgres: image: postgres:latest - container_name: postgres + container_name: siren-postgres env_file: *env environment: POSTGRES_USER: ${DATABASE_USER} diff --git a/src/bot/commands/audio/mod.rs b/src/bot/commands/audio/mod.rs index 55dc3ad..6e91387 100644 --- a/src/bot/commands/audio/mod.rs +++ b/src/bot/commands/audio/mod.rs @@ -1,10 +1,6 @@ use std::sync::Arc; use reqwest::Url; -use serenity::all::{ - CommandInteraction, CreateInteractionResponse, CreateInteractionResponseMessage, - EditInteractionResponse, -}; use serenity::client::Cache; use serenity::model::prelude::{GuildId, ChannelId}; use serenity::model::user::User; @@ -55,31 +51,6 @@ pub async fn leave_voice_channel(manager: &Arc, guild_id: &GuildId) -> Ok(()) } -pub async fn process_message(ctx: &Context, command: &CommandInteraction) { - create_response(&ctx, &command, format!("Processing...")).await; -} - -pub async fn create_response(ctx: &Context, command: &CommandInteraction, content: String) { - let data = CreateInteractionResponseMessage::new().content(content.to_owned()); - let builder = CreateInteractionResponse::Message(data); - match command.create_response(&ctx.http, builder).await { - Ok(_) => {} - Err(err) => { - log::error!("Failed to create response for {content}\n{err}"); - } - }; -} - -pub async fn edit_response(ctx: &Context, command: &CommandInteraction, content: String) { - let builder = EditInteractionResponse::new().content(content.to_owned()); - match command.edit_response(&ctx.http, builder).await { - Ok(_) => {} - Err(err) => { - log::error!("Failed to create response for {content}\n{err}"); - } - } -} - /** * Checks if a URL is valid and if it is a playlist. * 1st tuple value is if the URL is valid. diff --git a/src/bot/commands/audio/mute.rs b/src/bot/commands/audio/mute.rs index ddb1550..163ff00 100644 --- a/src/bot/commands/audio/mute.rs +++ b/src/bot/commands/audio/mute.rs @@ -3,11 +3,13 @@ use serenity::{ prelude::*, }; -use super::{edit_response, get_songbird, process_message}; +use crate::bot::commands::{edit_response, process_message}; + +use super::get_songbird; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Create the initial response - process_message(&ctx, &command).await; + process_message(&ctx, &command, false).await; // Get the songbird manager let manager = get_songbird(ctx).await; diff --git a/src/bot/commands/audio/pause.rs b/src/bot/commands/audio/pause.rs index 79cbb3d..e16e6c2 100644 --- a/src/bot/commands/audio/pause.rs +++ b/src/bot/commands/audio/pause.rs @@ -3,11 +3,13 @@ use serenity::{ prelude::*, }; -use super::{edit_response, get_songbird, process_message}; +use crate::bot::commands::{edit_response, process_message}; + +use super::get_songbird; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Create the initial response - process_message(&ctx, &command).await; + process_message(&ctx, &command, false).await; // Get the songbird manager let manager = get_songbird(ctx).await; diff --git a/src/bot/commands/audio/play.rs b/src/bot/commands/audio/play.rs index 56feae4..355a029 100644 --- a/src/bot/commands/audio/play.rs +++ b/src/bot/commands/audio/play.rs @@ -13,9 +13,9 @@ use crate::bot::ytdlp::{PlaylistItem, YtDlp}; use crate::error::{SirenResult, Error as SirenError}; use crate::HttpKey; -use super::{ - create_response, edit_response, get_songbird, is_valid_url, join_voice_channel, process_message, -}; +use super::{get_songbird, is_valid_url, join_voice_channel}; + +use crate::bot::commands::{create_response, edit_response, process_message}; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Process the command options @@ -26,13 +26,13 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { "{} attempted to play a track without a track option", command.user.id.get() ); - create_response(&ctx, &command, format!("Track option is missing")).await; + create_response(&ctx, &command, format!("Track option is missing"), false).await; return; } }; // Create the initial response - process_message(&ctx, &command).await; + process_message(&ctx, &command, false).await; // Get the songbird manager let manager = get_songbird(ctx).await; diff --git a/src/bot/commands/audio/resume.rs b/src/bot/commands/audio/resume.rs index 51b4206..d503a46 100644 --- a/src/bot/commands/audio/resume.rs +++ b/src/bot/commands/audio/resume.rs @@ -3,11 +3,13 @@ use serenity::{ prelude::*, }; -use super::{edit_response, get_songbird, process_message}; +use crate::bot::commands::{edit_response, process_message}; + +use super::get_songbird; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Create the initial response - process_message(&ctx, &command).await; + process_message(&ctx, &command, false).await; // Get the songbird manager let manager = get_songbird(ctx).await; diff --git a/src/bot/commands/audio/skip.rs b/src/bot/commands/audio/skip.rs index 8b22713..76f7066 100644 --- a/src/bot/commands/audio/skip.rs +++ b/src/bot/commands/audio/skip.rs @@ -3,11 +3,13 @@ use serenity::{ prelude::*, }; -use super::{edit_response, get_songbird, process_message}; +use crate::bot::commands::{edit_response, process_message}; + +use super::get_songbird; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Create the initial response - process_message(&ctx, &command).await; + process_message(&ctx, &command, false).await; // Get the songbird manager let manager = get_songbird(ctx).await; diff --git a/src/bot/commands/audio/stop.rs b/src/bot/commands/audio/stop.rs index 7897144..ccedbb4 100644 --- a/src/bot/commands/audio/stop.rs +++ b/src/bot/commands/audio/stop.rs @@ -3,11 +3,13 @@ use serenity::{ prelude::*, }; -use super::{edit_response, get_songbird, process_message}; +use crate::bot::commands::{edit_response, process_message}; + +use super::get_songbird; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Create the initial response - process_message(&ctx, &command).await; + process_message(&ctx, &command, false).await; // Get the songbird manager let manager = get_songbird(ctx).await; diff --git a/src/bot/commands/audio/volume.rs b/src/bot/commands/audio/volume.rs index fe7e911..b55a84c 100644 --- a/src/bot/commands/audio/volume.rs +++ b/src/bot/commands/audio/volume.rs @@ -9,7 +9,9 @@ use songbird::Songbird; use crate::data::guilds::GuildCache; -use super::{create_response, edit_response, get_songbird, process_message}; +use crate::bot::commands::{create_response, edit_response, process_message}; + +use super::get_songbird; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Process the command options @@ -20,13 +22,13 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { "{} attempted to change the volume without a volume option", command.user.id.get() ); - create_response(&ctx, &command, format!("Volume option is missing")).await; + create_response(&ctx, &command, format!("Volume option is missing"), false).await; return; } }; // Create the initial response - process_message(&ctx, &command).await; + process_message(&ctx, &command, false).await; // Get the songbird manager let manager = get_songbird(ctx).await; diff --git a/src/bot/commands/event/schedule.rs b/src/bot/commands/event/schedule.rs index d168011..ec132ca 100644 --- a/src/bot/commands/event/schedule.rs +++ b/src/bot/commands/event/schedule.rs @@ -5,11 +5,11 @@ use serenity::all::{ CreateEmbed, CreateEmbedFooter, EditInteractionResponse, Timestamp, }; -use crate::{bot::commands::audio::create_response, data::events::Event}; +use crate::{bot::commands::create_response, data::events::Event}; pub async fn run(ctx: &Context, command: &CommandInteraction) { // Create the initial response - create_response(&ctx, &command, format!(".....")).await; + create_response(&ctx, &command, format!("Processing..."), true).await; // Process the command options let title = command.data.options.get(0).unwrap().value.as_str().unwrap(); diff --git a/src/bot/commands/fun/roll.rs b/src/bot/commands/fun/roll.rs index ae2596a..7d48515 100644 --- a/src/bot/commands/fun/roll.rs +++ b/src/bot/commands/fun/roll.rs @@ -3,10 +3,17 @@ use serenity::all::{ CommandInteraction, CommandOptionType, Context, CreateCommand, CreateCommandOption, }; -use crate::bot::commands::audio::{create_response, edit_response}; +use crate::bot::commands::{create_response, create_dm, edit_response}; pub async fn run(ctx: &Context, command: &CommandInteraction) { - create_response(&ctx, &command, format!(".....")).await; + let hidden = match command.data.options.get(1) { + Some(o) => match o.value.as_bool() { + Some(b) => b, + None => false, + }, + None => false, + }; + create_response(&ctx, &command, format!("Rolling..."), hidden).await; let dice_string = match command.data.options.get(0) { Some(o) => match o.value.as_str() { Some(s) => s.split_whitespace().collect::(), @@ -33,7 +40,8 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { rolls.push(roll); } let response = format!( - "{}d{}{} = {}", + "🎲 **{}** (Rolled {}d{}{})", + total + (modifier as u32), count, sides, if modifier > 0 { @@ -42,8 +50,7 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) { format!("-{}", modifier) } else { "".to_string() - }, - total + (modifier as u32) + } ); edit_response(&ctx, &command, response).await; } @@ -84,10 +91,18 @@ fn parse_dice(dice: &str) -> Result<(u32, u32, i32), String> { if n == 4 || n == 6 || n == 8 || n == 10 || n == 12 || n == 20 || n == 100 { n } else { - return Err(format!("Invalid dice sides: {}", s)); + return Err(format!( + "Expected one of d4, d6, d8, d10, d12, d20, d100 but received d{}", + s + )); } } - Err(_) => return Err(format!("Invalid dice sides: {}", 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)), }; @@ -113,4 +128,12 @@ pub fn register() -> CreateCommand { .add_option( CreateCommandOption::new(CommandOptionType::String, "dice", "Dice to roll").required(true), ) + .add_option( + CreateCommandOption::new( + CommandOptionType::Boolean, + "hidden", + "Whether the roll should be hidden", + ) + .required(false), + ) } diff --git a/src/bot/commands/mod.rs b/src/bot/commands/mod.rs index 0c6d1e5..ad549a4 100644 --- a/src/bot/commands/mod.rs +++ b/src/bot/commands/mod.rs @@ -1,5 +1,59 @@ +use serenity::prelude::*; +use serenity::all::{ + CommandInteraction, CreateInteractionResponse, CreateInteractionResponseMessage, CreateMessage, + EditInteractionResponse, InteractionResponseFlags, Message, +}; + pub mod audio; pub mod chat; pub mod event; pub mod fun; pub mod utility; + +pub async fn process_message(ctx: &Context, command: &CommandInteraction, private: bool) { + create_response(&ctx, &command, format!("Processing..."), private).await; +} + +pub async fn create_dm( + ctx: &Context, + command: &CommandInteraction, + content: String, +) -> Option { + let data = CreateMessage::new().content(content.to_owned()); + return match command.user.direct_message(ctx, data).await { + Ok(message) => Some(message), + Err(err) => { + log::error!("Failed to create direct message for {content}\n{err}"); + None + } + }; +} + +pub async fn create_response( + ctx: &Context, + command: &CommandInteraction, + content: String, + private: bool, +) { + let mut data = CreateInteractionResponseMessage::new().content(content.to_owned()); + if private { + data = data.flags(InteractionResponseFlags::EPHEMERAL); + } + let builder = CreateInteractionResponse::Message(data); + match command.create_response(&ctx.http, builder).await { + Ok(_) => {} + Err(err) => { + log::error!("Failed to create response for {content}\n{err}"); + } + }; +} + +pub async fn edit_response(ctx: &Context, command: &CommandInteraction, content: String) { + let builder = EditInteractionResponse::new().content(content.to_owned()); + match command.edit_response(&ctx.http, builder).await { + Ok(_) => {} + Err(err) => { + log::error!("Failed to create response for {content}\n{err}"); + } + } +} diff --git a/src/bot/handler.rs b/src/bot/handler.rs index b22ef5e..535f197 100644 --- a/src/bot/handler.rs +++ b/src/bot/handler.rs @@ -6,7 +6,7 @@ use serenity::prelude::*; use crate::data::guilds::GuildCache; use super::{commands, oai}; -use super::commands::audio::create_response; +use super::commands::create_response; pub struct Handler { // Open AI Config @@ -62,7 +62,7 @@ impl EventHandler for Handler { "ping" => commands::utility::ping::run(&command.data.options), _ => "Unknown command".to_string(), }; - create_response(&ctx, &command, content).await; + create_response(&ctx, &command, content, false).await; } } }