diff --git a/bot-serenityutils/src/lib.rs b/bot-serenityutils/src/lib.rs index d04f074..ed1e686 100644 --- a/bot-serenityutils/src/lib.rs +++ b/bot-serenityutils/src/lib.rs @@ -1,4 +1,5 @@ pub mod core; +pub mod ephemeral_message; pub mod error; +pub mod macros; pub mod menu; -pub mod ephemeral_message; diff --git a/bot-serenityutils/src/macros.rs b/bot-serenityutils/src/macros.rs new file mode 100644 index 0000000..a3d3870 --- /dev/null +++ b/bot-serenityutils/src/macros.rs @@ -0,0 +1,16 @@ +/// Forwards the error directly to the user +/// without having to accept it in any handler. +/// Can only be used in async functions that return a Result. +#[macro_export] +macro_rules! forward_error { + ($ctx:expr,$channel_id:expr,$result:expr) => { + match $result { + Err(e) => { + use bot_serenityutils::{core::SHORT_TIMEOUT, ephemeral_message::EphemeralMessage}; + $channel_id.say($ctx, format!("‼️ {}", e)).await?; + return Ok(()); + } + Ok(v) => v, + } + }; +} diff --git a/src/commands/misc/time.rs b/src/commands/misc/time.rs index 6e4b077..760d6ca 100644 --- a/src/commands/misc/time.rs +++ b/src/commands/misc/time.rs @@ -17,13 +17,13 @@ async fn time(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { let second_timezone = args.single::().ok(); let from_timezone: Tz = if let Some(first) = &first_timezone { - first.parse::()? + forward_error!(ctx, msg.channel_id, first.parse::()) } else { Tz::UTC }; let to_timezone = if let Some(second) = &second_timezone { - second.parse::()? + forward_error!(ctx, msg.channel_id, second.parse::()) } else { Tz::UTC }; @@ -33,18 +33,25 @@ async fn time(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { } else { let now = Utc::now(); if second_timezone.is_some() { - from_timezone.datetime_from_str( - &format!("{} {}:00", now.format("%Y-%m-%d"), &*when), - "%Y-%m-%d %H:%M:%S", - )? + forward_error!( + ctx, + msg.channel_id, + from_timezone.datetime_from_str( + &format!("{} {}:00", now.format("%Y-%m-%d"), &*when), + "%Y-%m-%d %H:%M:%S", + ) + ) } else { let timezone: Tz = "UTC".parse().unwrap(); - timezone - .datetime_from_str( + forward_error!( + ctx, + msg.channel_id, + timezone.datetime_from_str( &format!("{} {}:00", now.format("%Y-%m-%d"), &*when), "%Y-%m-%d %H:%M:%S", - )? - .with_timezone(&from_timezone) + ) + ) + .with_timezone(&from_timezone) } }; diff --git a/src/commands/music/clear_queue.rs b/src/commands/music/clear_queue.rs index 77a9edc..da3b11f 100644 --- a/src/commands/music/clear_queue.rs +++ b/src/commands/music/clear_queue.rs @@ -23,7 +23,11 @@ async fn clear_queue(ctx: &Context, msg: &Message) -> CommandResult { } log::debug!("Clearing queue for guild {}", guild.id); - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); { let mut queue_lock = queue.lock().await; queue_lock.clear(); diff --git a/src/commands/music/current.rs b/src/commands/music/current.rs index 0800cd1..2bc9259 100644 --- a/src/commands/music/current.rs +++ b/src/commands/music/current.rs @@ -19,7 +19,11 @@ async fn current(ctx: &Context, msg: &Message) -> CommandResult { let guild = msg.guild(&ctx.cache).await.unwrap(); log::debug!("Displaying current song for queue in {}", guild.id); - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); let current = { let queue_lock = queue.lock().await; diff --git a/src/commands/music/join.rs b/src/commands/music/join.rs index 84d3f0a..22b9d37 100644 --- a/src/commands/music/join.rs +++ b/src/commands/music/join.rs @@ -20,10 +20,18 @@ async fn join(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { if is_dj(ctx, guild.id, &msg.author).await? { ChannelId(arg) } else { - get_channel_for_author(&msg.author.id, &guild)? + forward_error!( + ctx, + msg.channel_id, + get_channel_for_author(&msg.author.id, &guild) + ) } } else { - get_channel_for_author(&msg.author.id, &guild)? + forward_error!( + ctx, + msg.channel_id, + get_channel_for_author(&msg.author.id, &guild) + ) }; log::debug!("Joining channel {} for guild {}", channel_id, guild.id); join_channel(ctx, channel_id, guild.id).await; diff --git a/src/commands/music/leave.rs b/src/commands/music/leave.rs index 230ff9b..37e0542 100644 --- a/src/commands/music/leave.rs +++ b/src/commands/music/leave.rs @@ -23,7 +23,11 @@ async fn leave(ctx: &Context, msg: &Message) -> CommandResult { } let manager = get_voice_manager(ctx).await; - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); let queue_lock = queue.lock().await; let handler = manager.get(guild.id); @@ -31,11 +35,11 @@ async fn leave(ctx: &Context, msg: &Message) -> CommandResult { let mut handler_lock = handler.lock().await; handler_lock.remove_all_global_events(); } - if let Some(current) = queue_lock.current() { - current.stop()?; - } if manager.get(guild.id).is_some() { + if let Some(current) = queue_lock.current() { + current.stop()?; + } manager.remove(guild.id).await?; EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| { m.content("👋 Left the Voice Channel") diff --git a/src/commands/music/lyrics.rs b/src/commands/music/lyrics.rs index 6244dcc..7dc1d79 100644 --- a/src/commands/music/lyrics.rs +++ b/src/commands/music/lyrics.rs @@ -16,7 +16,11 @@ async fn lyrics(ctx: &Context, msg: &Message) -> CommandResult { let guild = msg.guild(&ctx.cache).await.unwrap(); log::debug!("Fetching lyrics for song playing in {}", guild.id); - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); let queue_lock = queue.lock().await; if let Some(current) = queue_lock.current() { diff --git a/src/commands/music/mod.rs b/src/commands/music/mod.rs index 1b28e2b..18c850f 100644 --- a/src/commands/music/mod.rs +++ b/src/commands/music/mod.rs @@ -194,7 +194,7 @@ fn get_channel_for_author(author_id: &UserId, guild: &Guild) -> BotResult CommandResul return Ok(()); } { - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); let mut queue_lock = queue.lock().await; queue_lock.move_position(pos1, pos2); } diff --git a/src/commands/music/pause.rs b/src/commands/music/pause.rs index 2cf9218..88d9cc0 100644 --- a/src/commands/music/pause.rs +++ b/src/commands/music/pause.rs @@ -22,7 +22,11 @@ async fn pause(ctx: &Context, msg: &Message) -> CommandResult { return Ok(()); } - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); let mut queue_lock = queue.lock().await; if let Some(_) = queue_lock.current() { diff --git a/src/commands/music/play.rs b/src/commands/music/play.rs index e53884a..70c96c6 100644 --- a/src/commands/music/play.rs +++ b/src/commands/music/play.rs @@ -33,7 +33,11 @@ async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult { handler = Some(join_channel(ctx, channel_id, guild.id).await); } - let handler_lock = handler.ok_or(CommandError::from("Not in a voice channel"))?; + let handler_lock = forward_error!( + ctx, + msg.channel_id, + handler.ok_or(CommandError::from("I'm not in a voice channel")) + ); let songs = get_songs_for_query(&ctx, msg, query).await?; diff --git a/src/commands/music/play_next.rs b/src/commands/music/play_next.rs index b06bb43..bc8b72f 100644 --- a/src/commands/music/play_next.rs +++ b/src/commands/music/play_next.rs @@ -35,7 +35,11 @@ async fn play_next(ctx: &Context, msg: &Message, args: Args) -> CommandResult { handler = Some(join_channel(ctx, channel_id, guild.id).await); } - let handler = handler.ok_or(CommandError::from("Not in a voice channel"))?; + let handler = forward_error!( + ctx, + msg.channel_id, + handler.ok_or(CommandError::from("I'm not in a voice channel")) + ); let mut songs = get_songs_for_query(&ctx, msg, query).await?; diff --git a/src/commands/music/queue.rs b/src/commands/music/queue.rs index 86fc790..cb7ba95 100644 --- a/src/commands/music/queue.rs +++ b/src/commands/music/queue.rs @@ -23,7 +23,11 @@ async fn queue(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { .map(|s| s.unwrap().to_lowercase()) .collect::>(); - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); let queue_lock = queue.lock().await; let songs: Vec<(usize, Song)> = queue_lock .entries() diff --git a/src/commands/music/remove_song.rs b/src/commands/music/remove_song.rs index 1c90b3f..344ccf1 100644 --- a/src/commands/music/remove_song.rs +++ b/src/commands/music/remove_song.rs @@ -27,7 +27,11 @@ async fn remove_song(ctx: &Context, msg: &Message, mut args: Args) -> CommandRes return Ok(()); } { - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); let mut queue_lock = queue.lock().await; queue_lock.remove(pos); } diff --git a/src/commands/music/shuffle.rs b/src/commands/music/shuffle.rs index 159e076..02c32c2 100644 --- a/src/commands/music/shuffle.rs +++ b/src/commands/music/shuffle.rs @@ -22,7 +22,11 @@ async fn shuffle(ctx: &Context, msg: &Message) -> CommandResult { msg.channel_id.say(ctx, "Requires DJ permissions").await?; return Ok(()); } - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); { let mut queue_lock = queue.lock().await; queue_lock.shuffle(); diff --git a/src/commands/music/skip.rs b/src/commands/music/skip.rs index 320641e..346163b 100644 --- a/src/commands/music/skip.rs +++ b/src/commands/music/skip.rs @@ -21,7 +21,11 @@ async fn skip(ctx: &Context, msg: &Message) -> CommandResult { return Ok(()); } log::debug!("Skipping song for guild {}", guild.id); - let queue = get_queue_for_guild(ctx, &guild.id).await?; + let queue = forward_error!( + ctx, + msg.channel_id, + get_queue_for_guild(ctx, &guild.id).await + ); let queue_lock = queue.lock().await; if let Some(current) = queue_lock.current() { diff --git a/src/main.rs b/src/main.rs index 2a8aa88..2843cbf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,9 @@ use crate::client::get_client; use crate::utils::logging::init_logger; +#[macro_use] +extern crate bot_serenityutils; + pub mod client; mod commands; pub mod handler;