use diesel::{ result::Error as DieselError, NotFound, }; use grate::tracing; use crate::{ commands::meme::send_meme, db::{ self, connection, find_meme, InvocationRecord, }, util, PoiseContext, RestVec, }; /// Post a meme. #[poise::command(prefix_command, guild_only, category = "memes", aliases("mem"))] pub async fn meme(ctx: PoiseContext<'_>, title: RestVec) -> anyhow::Result<()> { let title = title.into_inner().join(" "); _meme(ctx, title.trim(), AudioPlayback::Optional).await } /// Post a random omen. #[poise::command(prefix_command, guild_only, category = "memes", discard_spare_arguments)] pub async fn omen(ctx: PoiseContext<'_>) -> anyhow::Result<()> { _meme(ctx, "", AudioPlayback::Optional).await } /// Post a random omen without audio. #[poise::command(prefix_command, guild_only, category = "memes", discard_spare_arguments)] pub async fn silentomen(ctx: PoiseContext<'_>) -> anyhow::Result<()> { _meme(ctx, "", AudioPlayback::Prohibited).await } /// Post a random omen with audio. #[poise::command(prefix_command, guild_only, category = "memes", discard_spare_arguments)] pub async fn audioomen(ctx: PoiseContext<'_>) -> anyhow::Result<()> { _meme(ctx, "", AudioPlayback::Required).await } /// Post a random meme with audio. #[poise::command(prefix_command, guild_only, category = "memes", aliases("audiomeme", "audiomem"))] pub async fn audio_meme(ctx: PoiseContext<'_>) -> anyhow::Result<()> { _meme(ctx, "", AudioPlayback::Required).await } /// Post a random meme without audio. #[poise::command( prefix_command, guild_only, category = "memes", aliases("silentmeme", "silentmem") )] pub async fn silent_meme(ctx: PoiseContext<'_>) -> anyhow::Result<()> { _meme(ctx, "", AudioPlayback::Prohibited).await } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)] pub(crate) enum AudioPlayback { Required, #[default] Optional, Prohibited, } pub(crate) async fn _meme( ctx: PoiseContext<'_>, args: impl AsRef, audio_playback: AudioPlayback, ) -> anyhow::Result<()> { let args = args.as_ref().trim(); if args.is_empty() || audio_playback != AudioPlayback::Optional { return rand_meme(ctx, audio_playback).await; } let guild_id = util::guild_id(ctx)?; let mut conn = connection().await?; let mem = match find_meme(&mut conn, args, guild_id.get()).await { Ok(x) => { InvocationRecord::create( &mut conn, ctx.author().id.get(), guild_id.get(), ctx.id(), x.id, false, ) .await?; x }, Err(e) => { return if let Some(NotFound) = e.downcast_ref::() { tracing::info!("requested meme not found in database"); util::reply(ctx, "c'mon baby, guesstimate").await?; Ok(()) } else { util::reply(ctx, "what in ryan's name").await?; Err(e.into()) }; }, }; send_meme(ctx, &mem, &mut conn).await } async fn rand_meme(ctx: PoiseContext<'_>, audio_playback: AudioPlayback) -> anyhow::Result<()> { let should_audio = util::users_listening(ctx).await?; let guild_id = util::guild_id(ctx)?; let mut conn = connection().await?; let mem = match audio_playback { AudioPlayback::Required => db::rand_audio_meme(&mut conn, guild_id.get()).await, AudioPlayback::Optional => db::rand_meme(&mut conn, should_audio, guild_id.get()).await, AudioPlayback::Prohibited => db::rand_silent_meme(&mut conn, guild_id.get()).await, }; match mem { Ok(Some(mem)) => { InvocationRecord::create( &mut conn, ctx.author().id.get(), util::guild_id(ctx)?.get(), ctx.id(), mem.id, true, ) .await?; send_meme(ctx, &mem, &mut conn).await?; Ok(()) }, Ok(None) => { tracing::info!("random meme not found"); util::reply(ctx, "i don't know any :(").await?; Ok(()) }, Err(e) => { if let Some(NotFound) = e.downcast_ref::() { tracing::info!("random meme not found"); util::reply(ctx, "i don't know any :(").await?; return Ok(()); } util::reply(ctx, "HELP").await?; Err(e.into()) }, } } /// Post a rare meme. #[poise::command(prefix_command, guild_only, category = "memes", aliases("raremem", "rarememe"))] pub async fn rare_meme(ctx: PoiseContext<'_>) -> anyhow::Result<()> { let guild = util::guild_id(ctx)?; let should_audio = util::users_listening(ctx).await?; let mut conn = connection().await?; let meme = db::rare_meme(&mut conn, should_audio, guild.get()).await; match meme { Ok(Some(meme)) => { InvocationRecord::create( &mut conn, ctx.author().id.get(), util::guild_id(ctx)?.get(), ctx.id(), meme.id, true, ) .await?; send_meme(ctx, &meme, &mut conn).await }, Ok(None) => { tracing::info!("rare meme not found"); util::reply(ctx, "i don't know any :(").await?; Ok(()) }, Err(e) => { if let Some(NotFound) = e.downcast_ref::() { tracing::info!("rare meme not found"); util::reply(ctx, "i don't know any :(").await?; return Ok(()); } util::reply(ctx, "THE MEME MARKET IS IN FREEFALL").await?; Err(e.into()) }, } }