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 ephemeral_message;
pub mod error;
pub mod macros;
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 from_timezone: Tz = if let Some(first) = &first_timezone {
first.parse::<Tz>()?
forward_error!(ctx, msg.channel_id, first.parse::<Tz>())
} else {
Tz::UTC
};
let to_timezone = if let Some(second) = &second_timezone {
second.parse::<Tz>()?
forward_error!(ctx, msg.channel_id, second.parse::<Tz>())
} 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)
}
};

@ -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();

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

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

@ -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")

@ -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() {

@ -194,7 +194,7 @@ fn get_channel_for_author(author_id: &UserId, guild: &Guild) -> BotResult<Channe
.voice_states
.get(author_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
@ -216,7 +216,7 @@ pub(crate) async fn get_queue_for_guild(
let queue = store
.music_queues
.get(guild_id)
.ok_or(BotError::from("No queue for server"))?
.ok_or(BotError::from("I'm not in a Voice Channel"))?
.clone();
Ok(queue)
}

@ -28,7 +28,11 @@ async fn move_song(ctx: &Context, msg: &Message, mut args: Args) -> 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);
}

@ -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() {

@ -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?;

@ -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?;

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

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

@ -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();

@ -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() {

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

Loading…
Cancel
Save