Improve error handling with forward_error macro

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/12/head
trivernis 3 years ago
parent bbf9f1ef93
commit 8d6ed995e0
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,4 +1,5 @@
pub mod core; pub mod core;
pub mod ephemeral_message;
pub mod error; pub mod error;
pub mod macros;
pub mod menu; pub mod menu;
pub mod ephemeral_message;

@ -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,
}
};
}

@ -17,13 +17,13 @@ async fn time(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let second_timezone = args.single::<String>().ok(); let second_timezone = args.single::<String>().ok();
let from_timezone: Tz = if let Some(first) = &first_timezone { let from_timezone: Tz = if let Some(first) = &first_timezone {
first.parse::<Tz>()? forward_error!(ctx, msg.channel_id, first.parse::<Tz>())
} else { } else {
Tz::UTC Tz::UTC
}; };
let to_timezone = if let Some(second) = &second_timezone { let to_timezone = if let Some(second) = &second_timezone {
second.parse::<Tz>()? forward_error!(ctx, msg.channel_id, second.parse::<Tz>())
} else { } else {
Tz::UTC Tz::UTC
}; };
@ -33,18 +33,25 @@ async fn time(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
} else { } else {
let now = Utc::now(); let now = Utc::now();
if second_timezone.is_some() { if second_timezone.is_some() {
from_timezone.datetime_from_str( forward_error!(
&format!("{} {}:00", now.format("%Y-%m-%d"), &*when), ctx,
"%Y-%m-%d %H:%M:%S", msg.channel_id,
)? from_timezone.datetime_from_str(
&format!("{} {}:00", now.format("%Y-%m-%d"), &*when),
"%Y-%m-%d %H:%M:%S",
)
)
} else { } else {
let timezone: Tz = "UTC".parse().unwrap(); let timezone: Tz = "UTC".parse().unwrap();
timezone forward_error!(
.datetime_from_str( ctx,
msg.channel_id,
timezone.datetime_from_str(
&format!("{} {}:00", now.format("%Y-%m-%d"), &*when), &format!("{} {}:00", now.format("%Y-%m-%d"), &*when),
"%Y-%m-%d %H:%M:%S", "%Y-%m-%d %H:%M:%S",
)? )
.with_timezone(&from_timezone) )
.with_timezone(&from_timezone)
} }
}; };

@ -23,7 +23,11 @@ async fn clear_queue(ctx: &Context, msg: &Message) -> CommandResult {
} }
log::debug!("Clearing queue for guild {}", guild.id); 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; let mut queue_lock = queue.lock().await;
queue_lock.clear(); queue_lock.clear();

@ -19,7 +19,11 @@ async fn current(ctx: &Context, msg: &Message) -> CommandResult {
let guild = msg.guild(&ctx.cache).await.unwrap(); let guild = msg.guild(&ctx.cache).await.unwrap();
log::debug!("Displaying current song for queue in {}", guild.id); 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 current = {
let queue_lock = queue.lock().await; let queue_lock = queue.lock().await;

@ -20,10 +20,18 @@ async fn join(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
if is_dj(ctx, guild.id, &msg.author).await? { if is_dj(ctx, guild.id, &msg.author).await? {
ChannelId(arg) ChannelId(arg)
} else { } else {
get_channel_for_author(&msg.author.id, &guild)? forward_error!(
ctx,
msg.channel_id,
get_channel_for_author(&msg.author.id, &guild)
)
} }
} else { } 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); log::debug!("Joining channel {} for guild {}", channel_id, guild.id);
join_channel(ctx, channel_id, guild.id).await; join_channel(ctx, channel_id, guild.id).await;

@ -23,7 +23,11 @@ async fn leave(ctx: &Context, msg: &Message) -> CommandResult {
} }
let manager = get_voice_manager(ctx).await; 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 queue_lock = queue.lock().await;
let handler = manager.get(guild.id); 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; let mut handler_lock = handler.lock().await;
handler_lock.remove_all_global_events(); handler_lock.remove_all_global_events();
} }
if let Some(current) = queue_lock.current() {
current.stop()?;
}
if manager.get(guild.id).is_some() { if manager.get(guild.id).is_some() {
if let Some(current) = queue_lock.current() {
current.stop()?;
}
manager.remove(guild.id).await?; manager.remove(guild.id).await?;
EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| { EphemeralMessage::create(&ctx.http, msg.channel_id, SHORT_TIMEOUT, |m| {
m.content("👋 Left the Voice Channel") m.content("👋 Left the Voice Channel")

@ -16,7 +16,11 @@ async fn lyrics(ctx: &Context, msg: &Message) -> CommandResult {
let guild = msg.guild(&ctx.cache).await.unwrap(); let guild = msg.guild(&ctx.cache).await.unwrap();
log::debug!("Fetching lyrics for song playing in {}", guild.id); 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; let queue_lock = queue.lock().await;
if let Some(current) = queue_lock.current() { if let Some(current) = queue_lock.current() {

@ -194,7 +194,7 @@ fn get_channel_for_author(author_id: &UserId, guild: &Guild) -> BotResult<Channe
.voice_states .voice_states
.get(author_id) .get(author_id)
.and_then(|voice_state| voice_state.channel_id) .and_then(|voice_state| voice_state.channel_id)
.ok_or(BotError::from("Not in a voice channel.")) .ok_or(BotError::from("You're not in a Voice Channel"))
} }
/// Returns the voice manager from the context /// Returns the voice manager from the context
@ -216,7 +216,7 @@ pub(crate) async fn get_queue_for_guild(
let queue = store let queue = store
.music_queues .music_queues
.get(guild_id) .get(guild_id)
.ok_or(BotError::from("No queue for server"))? .ok_or(BotError::from("I'm not in a Voice Channel"))?
.clone(); .clone();
Ok(queue) Ok(queue)
} }

@ -28,7 +28,11 @@ async fn move_song(ctx: &Context, msg: &Message, mut args: Args) -> CommandResul
return Ok(()); 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; let mut queue_lock = queue.lock().await;
queue_lock.move_position(pos1, pos2); queue_lock.move_position(pos1, pos2);
} }

@ -22,7 +22,11 @@ async fn pause(ctx: &Context, msg: &Message) -> CommandResult {
return Ok(()); 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; let mut queue_lock = queue.lock().await;
if let Some(_) = queue_lock.current() { if let Some(_) = queue_lock.current() {

@ -33,7 +33,11 @@ async fn play(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
handler = Some(join_channel(ctx, channel_id, guild.id).await); 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?; let songs = get_songs_for_query(&ctx, msg, query).await?;

@ -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); 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?; let mut songs = get_songs_for_query(&ctx, msg, query).await?;

@ -23,7 +23,11 @@ async fn queue(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
.map(|s| s.unwrap().to_lowercase()) .map(|s| s.unwrap().to_lowercase())
.collect::<Vec<String>>(); .collect::<Vec<String>>();
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 queue_lock = queue.lock().await;
let songs: Vec<(usize, Song)> = queue_lock let songs: Vec<(usize, Song)> = queue_lock
.entries() .entries()

@ -27,7 +27,11 @@ async fn remove_song(ctx: &Context, msg: &Message, mut args: Args) -> CommandRes
return Ok(()); 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; let mut queue_lock = queue.lock().await;
queue_lock.remove(pos); queue_lock.remove(pos);
} }

@ -22,7 +22,11 @@ async fn shuffle(ctx: &Context, msg: &Message) -> CommandResult {
msg.channel_id.say(ctx, "Requires DJ permissions").await?; msg.channel_id.say(ctx, "Requires DJ permissions").await?;
return Ok(()); 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; let mut queue_lock = queue.lock().await;
queue_lock.shuffle(); queue_lock.shuffle();

@ -21,7 +21,11 @@ async fn skip(ctx: &Context, msg: &Message) -> CommandResult {
return Ok(()); return Ok(());
} }
log::debug!("Skipping song for guild {}", guild.id); 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; let queue_lock = queue.lock().await;
if let Some(current) = queue_lock.current() { if let Some(current) = queue_lock.current() {

@ -1,6 +1,9 @@
use crate::client::get_client; use crate::client::get_client;
use crate::utils::logging::init_logger; use crate::utils::logging::init_logger;
#[macro_use]
extern crate bot_serenityutils;
pub mod client; pub mod client;
mod commands; mod commands;
pub mod handler; pub mod handler;

Loading…
Cancel
Save