use diesel::{ result::Error as DieselError, NotFound, }; use itertools::Itertools; use log::info; use serenity::{ framework::standard::{ macros::command, Args, CommandError, CommandResult, }, futures::TryFutureExt, model::channel::Message, prelude::*, }; use crate::{ commands::meme::send_meme, db::{ self, connection, find_meme, InvocationRecord, }, util, }; #[command] #[aliases("mem")] pub async fn meme(ctx: &Context, msg: &Message, args: Args) -> CommandResult { _meme(ctx, msg, args, AudioPlayback::Optional).await } #[command] pub async fn omen(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { let args = Args::new("", &[]); _meme(ctx, msg, args, AudioPlayback::Optional).await } #[command] pub async fn silentomen(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { let args = Args::new("", &[]); _meme(ctx, msg, args, AudioPlayback::Prohibited).await } #[command] pub async fn audioomen(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { let args = Args::new("", &[]); _meme(ctx, msg, args, AudioPlayback::Required).await } #[command] #[aliases("audiomeme", "audiomem")] pub async fn audio_meme(ctx: &Context, msg: &Message, args: Args) -> CommandResult { _meme(ctx, msg, args, AudioPlayback::Required).await } #[command] #[aliases("silentmeme", "silentmem")] pub async fn silent_meme(ctx: &Context, msg: &Message, args: Args) -> CommandResult { _meme(ctx, msg, args, AudioPlayback::Prohibited).await } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] enum AudioPlayback { Required, Optional, Prohibited, } async fn _meme( ctx: &Context, msg: &Message, args: Args, audio_playback: AudioPlayback, ) -> CommandResult { if args.is_empty() || audio_playback != AudioPlayback::Optional { return rand_meme(ctx, msg, audio_playback).await; } let search = args.raw().join(" "); let mut conn = connection()?; let mem = match find_meme(&mut conn, search) { Ok(x) => { InvocationRecord::create(&mut conn, msg.author.id.get(), msg.id.get(), x.id, false)?; x }, Err(e) => { return if let Some(NotFound) = e.downcast_ref::() { info!("requested meme not found in database"); util::send(ctx, msg.channel_id, "c'mon baby, guesstimate", msg.tts) .await .map_err(CommandError::from) } else { util::send(ctx, msg.channel_id, "what in ryan's name", msg.tts).await?; Err(e.into()) }; }, }; send_meme(ctx, &mem, &mut conn, msg).await } async fn rand_meme( ctx: &Context, message: &Message, audio_playback: AudioPlayback, ) -> CommandResult { let mut conn = connection()?; let should_audio = util::users_listening(ctx).await?; let mem = match audio_playback { AudioPlayback::Required => db::rand_audio_meme(&mut conn), AudioPlayback::Optional => db::rand_meme(&mut conn, should_audio), AudioPlayback::Prohibited => db::rand_silent_meme(&mut conn), }; match mem { Ok(mem) => { InvocationRecord::create( &mut conn, message.author.id.get(), message.id.get(), mem.id, true, )?; send_meme(ctx, &mem, &mut conn, message).await?; Ok(()) }, Err(e) => { if let Some(NotFound) = e.downcast_ref::() { info!("random meme not found"); return util::send(ctx, message.channel_id, "i don't know any :(", message.tts) .map_err(CommandError::from) .await; } util::send(ctx, message.channel_id, "HELP", message.tts).await?; Err(e.into()) }, } } #[command] #[aliases("rarememe", "raremem")] pub async fn rare_meme(ctx: &Context, msg: &Message, _args: Args) -> CommandResult { let should_audio = util::users_listening(ctx).await?; let mut conn = connection()?; let meme = db::rare_meme(&mut conn, should_audio); match meme { Ok(meme) => { InvocationRecord::create(&mut conn, msg.author.id.get(), msg.id.get(), meme.id, true)?; send_meme(ctx, &meme, &mut conn, msg).await }, Err(e) => { if let Some(NotFound) = e.downcast_ref::() { info!("rare meme not found"); return util::send(ctx, msg.channel_id, "i don't know any :(", msg.tts) .map_err(CommandError::from) .await; } util::send(ctx, msg.channel_id, "THE MEME MARKET IS IN FREEFALL", msg.tts) .map_err(CommandError::from) .await?; Err(e.into()) }, } }