use diesel_async::AsyncPgConnection; use grate::tracing; use rand::random; use serenity::{ all::ReactionType, async_trait, builder::{ CreateAttachment, CreateMessage, }, }; use songbird::input::{ core::{ io::MediaSource, probe::Hint, }, AudioStream, AudioStreamError, Compose, Input, }; pub use self::{ create::*, delete::*, history::*, invoke::*, }; use crate::{ commands::playback::songbird, db::{ Audio, Meme, }, util, PoiseContext, CONFIG, }; mod create; mod delete; mod history; pub(crate) mod invoke; pub fn commands() -> Vec> { vec![ meme(), silent_meme(), audio_meme(), rare_meme(), omen(), silentomen(), audioomen(), addmeme(), addaudiomeme(), delmeme(), history(), stats(), memers(), wat(), query(), ] } async fn send_meme( ctx: PoiseContext<'_>, t: &Meme, conn: &mut AsyncPgConnection, ) -> anyhow::Result<()> { let should_tts = t.content.as_ref().map(|t| !t.is_empty()).unwrap_or(false) && random::() % 25 == 0; tracing::debug!("sending meme (tts: {}): {:?}", should_tts, t); let image = t.image(conn).await; let audio = t.audio(conn).await; let cmsg = { let ret = CreateMessage::default().tts(should_tts); match t.content { Some(ref text) if !text.is_empty() => ret.content(text), _ => ret, } }; match image { Some(image) => { let image = image?; let att = CreateAttachment::bytes(image.data.as_slice(), &image.filename); ctx.channel_id().send_files(ctx, vec![att], cmsg).await?; }, None => { if t.content.is_some() { ctx.channel_id().send_message(ctx, cmsg).await?; } }, }; if let Some(audio) = audio { let audio = audio?; let (_sb, call) = songbird(ctx).await?; let mut call = call.lock().await; if call.current_channel().is_none() { call.join(CONFIG.discord.voice_channel()).await?; } call.enqueue_input(Input::Lazy(Box::new(audio))).await; util::react(ctx, ReactionType::Unicode("📣".to_owned())).await?; } Ok(()) } #[async_trait] impl Compose for Audio { fn create(&mut self) -> Result>, AudioStreamError> { let ms = std::io::Cursor::new(self.data.clone()); let ms: Box = Box::new(ms); let mut hint = Hint::new(); hint.mime_type("audio/opus"); Ok(AudioStream { input: ms, hint: Some(hint), }) } #[inline] async fn create_async( &mut self, ) -> Result>, AudioStreamError> { self.create() } #[inline] fn should_create_async(&self) -> bool { false } }