use diesel_async::AsyncPgConnection; use log::debug; use rand::random; use serenity::{ all::ReactionType, async_trait, builder::{ CreateAttachment, CreateMessage, }, framework::standard::{ macros::group, CommandResult, }, model::channel::Message, prelude::*, }; use songbird::input::{ core::{ io::MediaSource, probe::Hint, }, AudioStream, AudioStreamError, Compose, Input, }; use crate::{ commands::songbird, db::{ Audio, Meme, }, CONFIG, }; pub use self::{ create::*, delete::*, history::*, invoke::*, }; mod create; mod delete; mod history; mod invoke; #[group] #[commands( meme, audio_meme, silent_meme, omen, audioomen, silentomen, addmeme, addaudiomeme, delmeme, wat, stats, history, rare_meme, memers, query )] struct Memes; async fn send_meme( ctx: &Context, t: &Meme, conn: &mut AsyncPgConnection, msg: &Message, ) -> CommandResult { let should_tts = t.content.as_ref().map(|t| !t.is_empty()).unwrap_or(false) && random::() % 25 == 0; 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); msg.channel_id.send_files(ctx, vec![att], cmsg).await?; }, None => { if t.content.is_some() { msg.channel_id.send_message(ctx, cmsg).await?; } }, }; if let Some(audio) = audio { let audio = audio?; let (_sb, call) = songbird(ctx, msg).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; msg.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 } }