From 96f3ee8387b7d38f7b5f32e7ecca6be6c3eede3b Mon Sep 17 00:00:00 2001 From: David Thomas Date: Fri, 6 Oct 2023 16:27:41 +0100 Subject: [PATCH] Rewrite error messages to be manual instead of formatted This helps translation and makes them read better --- Cargo.lock | 54 ++++++++++++++++----------------- src/commands/main.rs | 34 ++++++++------------- src/errors.rs | 72 ++++++++++++++++++++++---------------------- src/main.rs | 55 ++++++++++++++++++--------------- src/traits.rs | 9 ++---- 5 files changed, 109 insertions(+), 115 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 451062b..f5d898e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,7 +92,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -192,9 +192,9 @@ checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -794,7 +794,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -1569,7 +1569,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -1677,9 +1677,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "5b1106fec09662ec6dd98ccac0f81cef56984d0b49f75c92d8cbad76e20c005c" dependencies = [ "unicode-ident", ] @@ -1807,9 +1807,9 @@ checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "reqwest" -version = "0.11.21" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78fdbab6a7e1d7b13cc8ff10197f47986b41c639300cc3c8158cac7847c9bbef" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ "base64 0.21.4", "bytes", @@ -1907,9 +1907,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.15" +version = "0.38.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" +checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" dependencies = [ "bitflags 2.4.0", "errno", @@ -2109,7 +2109,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -2131,7 +2131,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -2158,7 +2158,7 @@ dependencies = [ [[package]] name = "serenity" version = "0.11.6" -source = "git+https://github.com/serenity-rs/serenity?branch=next#7025a807e32a73341b4cc6276ff6c2a159b58b1a" +source = "git+https://github.com/serenity-rs/serenity?branch=next#012b0512e86a9f2429391ff6270555aba7895c5e" dependencies = [ "arrayvec", "async-trait", @@ -2189,7 +2189,7 @@ dependencies = [ [[package]] name = "serenity-voice-model" version = "0.1.1" -source = "git+https://github.com/serenity-rs/serenity?branch=next#7025a807e32a73341b4cc6276ff6c2a159b58b1a" +source = "git+https://github.com/serenity-rs/serenity?branch=next#012b0512e86a9f2429391ff6270555aba7895c5e" dependencies = [ "bitflags 2.4.0", "enum_primitive", @@ -2222,9 +2222,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b21f559e07218024e7e9f90f96f601825397de0e25420135f7f952453fed0b" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -2550,7 +2550,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -2668,9 +2668,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.37" +version = "2.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" dependencies = [ "proc-macro2", "quote", @@ -2743,7 +2743,7 @@ checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -2826,7 +2826,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -2967,7 +2967,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", ] [[package]] @@ -3282,7 +3282,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", "wasm-bindgen-shared", ] @@ -3316,7 +3316,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.37", + "syn 2.0.38", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -3480,9 +3480,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.15" +version = "0.5.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" +checksum = "037711d82167854aff2018dfd193aa0fef5370f456732f0d5a0c59b0f1b4b907" dependencies = [ "memchr", ] diff --git a/src/commands/main.rs b/src/commands/main.rs index 8c71f36..9c7e4ce 100644 --- a/src/commands/main.rs +++ b/src/commands/main.rs @@ -33,10 +33,10 @@ async fn channel_check(ctx: &Context<'_>, author_vc: Option if setup_id == channel_id.get() as i64 || author_vc == Some(channel_id) { Ok(true) } else { - ctx.send_error( - ctx.gettext("you ran this command in the wrong channel"), - Some(ctx.gettext("do `/channel` get the channel that has been setup")) - ).await?; + let msg = ctx.gettext("You ran this command in the wrong channel, please move to <#{channel_id}>.") + .replace("{channel_id}", &setup_id.to_string()); + + ctx.send_error(msg).await?; Ok(false) } } @@ -50,8 +50,7 @@ async fn channel_check(ctx: &Context<'_>, author_vc: Option )] pub async fn join(ctx: Context<'_>) -> CommandResult { let author_vc = require!(ctx.author_vc(), ctx.send_error( - ctx.gettext("you need to be in a voice channel to make me join your voice channel"), - Some(ctx.gettext("join a voice channel and try again")), + ctx.gettext("I cannot join your voice channel unless you are in one!").to_owned() ).await.map(drop)); if !channel_check(&ctx, Some(author_vc)).await? { @@ -67,11 +66,8 @@ pub async fn join(ctx: Context<'_>) -> CommandResult { let bot_member = guild_id.member(ctx, bot_id).await?; if let Some(communication_disabled_until) = bot_member.communication_disabled_until { if communication_disabled_until > serenity::Timestamp::now() { - ctx.send_error( - ctx.gettext("I am timed out"), - Some(ctx.gettext("ask a moderator to remove the timeout")) - ).await?; - + let msg = ctx.gettext("I am timed out, please ask a moderator to remove the timeout"); + ctx.send_error(msg.to_owned()).await?; return Ok(()) } } @@ -85,14 +81,10 @@ pub async fn join(ctx: Context<'_>) -> CommandResult { channel.permissions_for_user(ctx, bot_id)?; if !missing_permissions.is_empty() { - ctx.send_error( - ctx.gettext("I do not have permissions to TTS in your voice channel"), - Some(&ctx - .gettext("please ask an administrator to give me: {missing_permissions}") - .replace("{missing_permissions}", &missing_permissions.get_permission_names().join(", ")) - ) - ).await?; + let msg = ctx.gettext("I do not have permission to TTS in your voice channel, please ask a server administrator to give me: {missing_permissions}") + .replace("{missing_permissions}", &missing_permissions.get_permission_names().join(", ")); + ctx.send_error(msg).await?; return Ok(()) } @@ -118,10 +110,8 @@ pub async fn join(ctx: Context<'_>) -> CommandResult { if let Err(err) = join_vc_result { return if let JoinError::TimedOut = err { - ctx.send_error( - ctx.gettext("a timeout occurred while joining your voice channel"), - Some(ctx.gettext("wait a few seconds and try again")) - ).await?; + let msg = ctx.gettext("I failed to join your voice channel, please check I have the right permissions and try again!"); + ctx.send_error(msg.to_owned()).await?; Ok(()) } else { Err(err.into()) diff --git a/src/errors.rs b/src/errors.rs index a817dbd..f556563 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -223,8 +223,9 @@ pub async fn handle_guild(name: &str, ctx: &serenity::Context, framework: Framew // Command Error handlers async fn handle_cooldown(ctx: Context<'_>, remaining_cooldown: std::time::Duration) -> Result<(), Error> { let cooldown_response = ctx.send_error( - &ctx.gettext("{command_name} is on cooldown").replace("{command_name}", &ctx.command().name), - Some(&ctx.gettext("try again in {} seconds").replace("{}", &format!("{:.1}", remaining_cooldown.as_secs_f32()))) + ctx.gettext("`/{command_name}` is on cooldown, please try again in {} seconds!") + .replace("{command_name}", &ctx.command().name) + .replace("{}", &format!("{:.1}", remaining_cooldown.as_secs_f32())) ).await?; if let poise::Context::Prefix(ctx) = ctx { @@ -248,28 +249,26 @@ async fn handle_cooldown(ctx: Context<'_>, remaining_cooldown: std::time::Durati } async fn handle_argparse(ctx: Context<'_>, error: Box, input: Option) -> Result<(), Error> { - let mut reason = None; - let fix = &ctx - .gettext("check out `/help {command}`") - .replace("{command}", &ctx.command().qualified_name); - - if error.is::() { - reason = Some(ctx.gettext("I cannot find the member: `{}`")); + let reason = if error.is::() { + ctx.gettext("I cannot find the member: `{}`") } else if error.is::() { - reason = Some(ctx.gettext("I cannot find the server: `{}`")); + ctx.gettext("I cannot find the server: `{}`") } else if error.is::() { - reason = Some(ctx.gettext("I cannot find the channel: `{}`")); + ctx.gettext("I cannot find the channel: `{}`") } else if error.is::() { - reason = Some(ctx.gettext("I cannot convert `{}` to a number")); + ctx.gettext("I cannot convert `{}` to a number") } else if error.is::() { - reason = Some(ctx.gettext("I cannot convert `{}` to True/False")); - } + ctx.gettext("I cannot convert `{}` to True/False") + } else { + ctx.gettext("I cannot understand your message") + }; - ctx.send_error( - reason.map(|r| r.replace("{}", &input.unwrap()).replace('`', "")).as_deref().unwrap_or("you typed the command wrong"), - Some(fix) - ).await?; + let reason = reason.replace("{}", &input.unwrap()); + let fix = ctx + .gettext("please check out `/help {command}`") + .replace("{command}", &ctx.command().qualified_name); + ctx.send_error(format!("{reason} {fix}")).await?; Ok(()) } @@ -319,31 +318,35 @@ pub async fn handle(error: poise::FrameworkError<'_, Data, Error>) -> Result<()> Some(author.name.clone()), Some(author.face()) ).await?; - ctx.send_error("an unknown error occurred", None).await?; + let msg = ctx.gettext("An unknown error occurred, please report this on the support server!"); + ctx.send_error(msg.to_owned()).await?; } poise::FrameworkError::ArgumentParse { error, ctx, input, .. } => handle_argparse(ctx, error, input).await?, poise::FrameworkError::CooldownHit { remaining_cooldown, ctx, .. } => handle_cooldown(ctx, remaining_cooldown).await?, poise::FrameworkError::MissingBotPermissions{missing_permissions, ctx, .. } => { - ctx.send_error( - &ctx.gettext("I cannot run `{command}` as I am missing permissions").replace("{command}", &ctx.command().name), - Some(&ctx.gettext("give me: {}").replace("{}", &missing_permissions.get_permission_names().join(", "))) - ).await?; + let msg = ctx.gettext("I cannot run this command as I am missing permissions, please ask an administrator of the server to give me: {}") + .replace("{}", &missing_permissions.get_permission_names().join(", ")); + + ctx.send_error(msg).await?; }, poise::FrameworkError::MissingUserPermissions{missing_permissions, ctx, ..} => { - ctx.send_error( - ctx.gettext("you cannot run this command"), - missing_permissions.map(|missing_permissions| (ctx - .gettext("ask an administrator for the following permissions: {}") + let msg = if let Some(missing_permissions) = missing_permissions { + ctx.gettext("You cannot run this command as you are missing permissions, please ask an administrator of the server to give you: {}") .replace("{}", &missing_permissions.get_permission_names().join(", ")) - )).as_deref() - ).await?; + } else { + ctx.gettext("You cannot run this command as you are missing permissions.").to_owned() + }; + + ctx.send_error(msg).await?; }, poise::FrameworkError::Setup { .. } => panic!("{error:#?}"), poise::FrameworkError::CommandCheckFailed { error, ctx, .. } => { if let Some(error) = error { error!("Premium Check Error: {:?}", error); - ctx.send_error(ctx.gettext("an unknown error occurred during the premium check"), None).await?; + + let msg = ctx.gettext("An unknown error occurred during the premium check, please report this on the support server!"); + ctx.send_error(msg.to_owned()).await?; } }, @@ -389,14 +392,11 @@ pub async fn handle(error: poise::FrameworkError<'_, Data, Error>) -> Result<()> poise::FrameworkError::UnknownCommand { .. } => {}, poise::FrameworkError::GuildOnly {ctx, ..} => { let error = ctx - .gettext("{command_name} cannot be used in private messages") + .gettext("`/{command_name}` cannot be used in private messages, please run this command in a server channel.") + .replace("{bot_name}", &ctx.cache().current_user().name) .replace("{command_name}", &ctx.command().qualified_name); - let fix = ctx - .gettext("try running it on a server with {bot_name} in") - .replace("{bot_name}", &ctx.serenity_context().cache.current_user().name); - - ctx.send_error(&error, Some(&fix)).await?; + ctx.send_error(error).await?; }, poise::FrameworkError::CommandPanic { .. } => panic!("Command panicked!"), poise::FrameworkError::__NonExhaustive(_) => unreachable!(), diff --git a/src/main.rs b/src/main.rs index 76a3dd7..129aad7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -260,30 +260,37 @@ async fn _main(start_time: std::time::SystemTime) -> Result<()> { }, command_check: Some(|ctx| Box::pin(async move { if ctx.author().bot { - Ok(false) - } else if let Some(guild_id) = ctx.guild_id() && let Some(required_role) = ctx.data().guilds_db.get(guild_id.into()).await?.required_role { - let required_role = serenity::RoleId::new(required_role as u64); - let member = ctx.author_member().await.try_unwrap()?; - - let is_admin = || { - let guild = require_guild!(ctx, Ok(false)); - let channel = guild.channels.get(&ctx.channel_id()).try_unwrap()?; - - let permissions = guild.user_permissions_in(channel, &member); - Ok(permissions.administrator()) - }; - - if member.roles.contains(&required_role) || is_admin()? { - Ok(true) - } else { - ctx.send_error( - "you do not have the required role to use this command", - Some(&format!("ask a server admin for {}", required_role.mention())) - ).await.map(|_| false).map_err(Into::into) - } - } else { - Ok(true) - } + return Ok(false) + }; + + let Some(guild_id) = ctx.guild_id() else { + return Ok(true) + }; + + let Some(required_role) = ctx.data().guilds_db.get(guild_id.into()).await?.required_role else { + return Ok(true) + }; + + let required_role = serenity::RoleId::new(required_role as u64); + let member = ctx.author_member().await.try_unwrap()?; + + let is_admin = || { + let guild = require_guild!(ctx, Ok(false)); + let channel = guild.channels.get(&ctx.channel_id()).try_unwrap()?; + + let permissions = guild.user_permissions_in(channel, &member); + Ok(permissions.administrator()) + }; + + if member.roles.contains(&required_role) || is_admin()? { + return Ok(true) + }; + + let msg = ctx.gettext("You do not have the required role to use this bot, ask a server administrator for {}.") + .replace("{}", &required_role.mention().to_string()); + + ctx.send_error(msg).await?; + Ok(false) })), ..poise::FrameworkOptions::default() }; diff --git a/src/traits.rs b/src/traits.rs index 942e2c9..2b72b02 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -13,7 +13,7 @@ pub trait PoiseContextExt { fn gettext<'a>(&'a self, translate: &'a str) -> &'a str; fn current_catalog(&self) -> Option<&gettext::Catalog>; - async fn send_error(&self, error: &str, fix: Option<&str>) -> Result>>; + async fn send_error(&self, error_message: String) -> Result>>; async fn neutral_colour(&self) -> u32; fn author_vc(&self) -> Option; @@ -76,7 +76,7 @@ impl PoiseContextExt for Context<'_> { } } - async fn send_error(&self, error: &str, fix: Option<&str>) -> Result>> { + async fn send_error(&self, error_message: String) -> Result>> { let author = self.author(); let serenity_ctx = self.serenity_context(); @@ -114,10 +114,7 @@ impl PoiseContextExt for Context<'_> { .colour(constants::RED) .title("An Error Occurred!") .author(serenity::CreateEmbedAuthor::new(name).icon_url(avatar_url)) - .description(format!( - "Sorry but {}, to fix this, please {error}!", - fix.unwrap_or("get in contact with us via the support server"), - )) + .description(error_message) .footer(serenity::CreateEmbedFooter::new(format!( "Support Server: {}", self.data().main_server_invite )))