diff options
Diffstat (limited to 'src/bot.rs')
| -rw-r--r-- | src/bot.rs | 169 |
1 files changed, 89 insertions, 80 deletions
@@ -1,9 +1,9 @@ use std::{ + collections::HashSet, fs::File, future::Future, path::PathBuf, pin::Pin, - result::Result as StdResult, str::FromStr, sync::Arc, }; @@ -21,22 +21,16 @@ use log::{ trace, warn, }; +use poise::{ + BoxFuture, + FrameworkError, +}; use serenity::{ all::{ GuildId, ReactionType, }, - async_trait, - framework::{ - standard::{ - BucketBuilder, - CommandError, - Configuration, - }, - StandardFramework, - }, model::{ - channel::Message, event::ResumedEvent, gateway::Ready, id::{ @@ -56,11 +50,13 @@ use songbird::{ use tokio::sync::Mutex; use crate::{ - commands::register_commands, + commands, config::CONFIG, util, util::OAUTH_URL, Error, + PoiseContext, + PoiseData, Result, }; @@ -123,7 +119,7 @@ impl EventHandler for Handler { struct SongbirdHandler(Arc<Mutex<Call>>); -#[async_trait] +#[serenity::async_trait] impl songbird::events::EventHandler for SongbirdHandler { async fn act(&self, _ctx: &EventContext<'_>) -> Option<Event> { let mut call = self.0.lock().await; @@ -161,112 +157,125 @@ lazy_static! { let result = restrict_ids.unwrap_or_default().into_iter().collect::<FnvHashSet<_>>(); - info!("restricted ids: {:?}", result); + info!("restricted ids: {result:?}"); result }; } -async fn framework() -> StandardFramework { - let builder = BucketBuilder::default().delay(1).limit(20).time_span(60); +fn on_err(err: FrameworkError<PoiseData, anyhow::Error>) -> BoxFuture<()> { + Box::pin(async move { + error!("error encountered: {err:?}"); - let framework = StandardFramework::new() - .before(before_handle) - .after(after_handle) - .bucket("Standard", builder) - .await; + if let Some(ctx) = err.ctx() { + if let Err(e) = util::react(ctx, ReactionType::Unicode("❌".to_owned())).await { + error!("reacting to failed message: {e}"); + } - let config = Configuration::default() - .allow_dm(false) - .with_whitespace(true) - .prefixes(ALL_PREFIXES.iter().map(|x| x.to_string())) - .ignore_bots(true) - .on_mention(None) - .owners(vec![CONFIG.discord.owner()].into_iter().collect()) - .case_insensitivity(true); + if let Err(e) = util::reply(ctx, "BANIC").await { + error!("sending BANIC: {e}"); + } + } + }) +} - framework.configure(config); +async fn framework() -> poise::Framework<PoiseData, anyhow::Error> { + let additional_prefixes = + ALL_PREFIXES.iter().skip(1).map(|x| poise::Prefix::Literal(x.to_owned())).collect(); - register_commands(framework) -} + let framework = poise::Framework::builder() + .options(poise::FrameworkOptions { + pre_command: before_handle, + post_command: after_handle, + on_error: on_err, + + command_check: Some(check), + + prefix_options: poise::PrefixFrameworkOptions { + prefix: ALL_PREFIXES.get(0).map(|&x| x.to_owned()), + additional_prefixes, + case_insensitive_commands: true, + mention_as_prefix: false, + ignore_bots: true, + ..Default::default() + }, + + commands: commands::commands(), + owners: HashSet::from_iter([CONFIG.discord.owner()]), + initialize_owners: false, + skip_checks_for_owners: true, -fn before_handle<'fut>( - ctx: &'fut Context, - message: &'fut Message, - cmd: &'fut str, -) -> Pin<Box<dyn Future<Output = bool> + Send + 'fut>> { - debug!("got command '{}' from user '{}' ({})", cmd, message.author.name, message.author.id); + ..Default::default() + }) + .setup(|_ctx, _ready, _framework| Box::pin(async move { Ok(()) })) + .build(); + + framework +} +fn check(ctx: PoiseContext) -> BoxFuture<anyhow::Result<bool>> { Box::pin(async move { - if !message.guild_id.map_or(false, |x| x == CONFIG.discord.guild()) { - info!("rejecting command '{}' from user '{}': wrong guild", cmd, message.author.name); - return false; + if !ctx.guild_id().map_or(false, |x| x == CONFIG.discord.guild()) { + info!( + "rejecting command '{}' from user '{}': wrong guild", + ctx.command().name, + ctx.author().name + ); + return Ok(false); } - if message.author.id == CONFIG.discord.owner() { - return true; + if ctx.author().id == CONFIG.discord.owner() { + return Ok(true); } - let restricted_prefix = - RESTRICTED_PREFIXES.iter().any(|prefix| message.content.starts_with(prefix)); + let restricted_prefix = RESTRICTED_PREFIXES.iter().any(|&prefix| ctx.prefix() == prefix); if !restricted_prefix { - return true; + return Ok(true); } const PERMITTED_WEEKDAY: chrono::Weekday = chrono::Weekday::Tue; - let user_is_restricted = RESTRICT_IDS.contains(&message.author.id.get()); + let user_is_restricted = RESTRICT_IDS.contains(&ctx.author().id.get()); let restrictions_flipped = chrono::Local::now().weekday() == PERMITTED_WEEKDAY; if user_is_restricted == restrictions_flipped { - return true; + return Ok(true); } let reason = if !restrictions_flipped { "restricted prefix".to_owned() } else { - format!("it is {:?}", PERMITTED_WEEKDAY) + format!("it is {PERMITTED_WEEKDAY:?}") }; - info!("rejecting command '{}' from user '{}': {}", cmd, message.author.name, reason); + info!( + "rejecting command '{}' from user '{}': {}", + ctx.command().name, + ctx.author().name, + reason + ); - match util::send_result(ctx, message.channel_id, "no", message.tts).await { - Err(e) => error!("sending restricted prefix response: {}", e), - Ok(msg_id) => { - let mut mp = MESSAGE_WATCH.lock().await; - mp.insert(message.id, msg_id); - }, - } + util::reply(ctx, "no").await?; - false + Ok(false) }) } -fn after_handle<'fut>( - ctx: &'fut Context, - msg: &'fut Message, - cmd: &'fut str, - err: StdResult<(), CommandError>, -) -> Pin<Box<dyn Future<Output = ()> + Send + 'fut>> { - Box::pin(async move { - match err { - Ok(()) => { - trace!("command '{}' completed successfully", cmd); - }, - - Err(e) => { - if let Err(e) = msg.react(&ctx, ReactionType::Unicode("❌".to_owned())).await { - error!("reacting to failed message: {}", e); - } +fn before_handle<'fut>(ctx: PoiseContext<'fut>) -> Pin<Box<dyn Future<Output = ()> + Send + 'fut>> { + debug!( + "got command '{}' from user '{}' ({})", + ctx.command().name, + ctx.author().name, + ctx.author().id + ); - if let Err(e) = util::send(ctx, msg.channel_id, "BANIC", msg.tts).await { - error!("sending BANIC: {}", e); - } + Box::pin(async {}) +} - error!("error encountered handling command '{}': {:?}", cmd, e); - }, - } +fn after_handle(ctx: PoiseContext) -> BoxFuture<()> { + Box::pin(async move { + trace!("command '{}' completed successfully", ctx.command().name); }) } |
