From a6f5334f984531cf2304b6333b138944517d3703 Mon Sep 17 00:00:00 2001 From: Nathan Perry Date: Sat, 30 Mar 2019 03:31:30 -0400 Subject: restructure meme module --- src/commands/meme/create.rs | 174 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 src/commands/meme/create.rs (limited to 'src/commands/meme/create.rs') diff --git a/src/commands/meme/create.rs b/src/commands/meme/create.rs new file mode 100644 index 0000000..245f067 --- /dev/null +++ b/src/commands/meme/create.rs @@ -0,0 +1,174 @@ +use std::{ + io::Read, + process::{ + Command, + Stdio, + }, +}; + +use diesel::result::Error as DieselError; +use serenity::{ + framework::standard::Args, + model::channel::Message, + prelude::*, +}; +use url::Url; + +use crate::{ + audio::{ + parse_times, + ytdl_url, + }, + commands::send, + db::{ + Audio, + connection, + Image, + NewMeme, + }, + Result, +}; + +pub fn addmeme(_: &mut Context, msg: &Message, args: Args) -> Result<()> { + let mut args = Args::new(args.rest(), &[" ".to_owned(), "\n".to_owned(), "\t".to_owned()]); + + let title = args.single_quoted::()?; + let text = args.rest().to_owned(); + + let text = if text.is_empty() { None } else { Some(text) }; + + let conn = connection()?; + + let image = msg.attachments.first() + .ok_or(::failure::err_msg("no attachment")) + .and_then(|att| { + let data = att.download()?; + Image::create(&conn, &att.filename, data, msg.author.id.0) + }) + .ok(); + + if image.is_none() && text.is_none() { + warn!("tried to create non-audio meme with no image or text"); + return send(msg.channel_id, "hahAA it's empty xdddd", msg.tts); + } + + let save_result = NewMeme { + title, + content: text, + image_id: image, + audio_id: None, + metadata_id: 0, + }.save(&conn, msg.author.id.0).map(|_| {}); + + use diesel::result::DatabaseErrorKind; + match save_result { + Ok(_) => msg.react("👌"), + Err(e) => { + if let Some(DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) = e.downcast_ref::() { + error!("tried to create meme that already exists"); + msg.react("❌")?; + return send(msg.channel_id, "that meme already exists", msg.tts); + } + + return Err(e); + } + } +} + +pub fn addaudiomeme(_: &mut Context, msg: &Message, args: Args) -> Result<()> { + let mut args = Args::new(args.rest(), &[" ".to_owned(), "\n".to_owned(), "\t".to_owned()]); + + let title = args.single_quoted::()?; + let audio_str = args.single_quoted::()?; + + let elems = audio_str.split_whitespace().collect::>(); + + if elems.len() == 0 { + send(msg.channel_id, "are you stupid", msg.tts)?; + return Err(::failure::err_msg("no audio link was provided")) + } + + let audio_link = Url::parse(elems[0])?; + let opts = elems[1..].join(" "); + let (start, end) = parse_times(opts); + + let youtube_url = ytdl_url(audio_link.as_str())?; + + let duration_opts = if let Some(e) = end { + vec! [ + "-ss".to_owned(), start.map_or_else( + || "00:00:00".to_owned(), + |s| format!("{:02}:{:02}:{:02}", s.num_hours(), s.num_minutes() % 60, s.num_seconds() % 60) + ), + + "-to".to_owned(), format!("{:02}:{:02}:{:02}", e.num_hours(), e.num_minutes() % 60, e.num_seconds() % 60), + ] + } else { + vec! [] + }; + + let ffmpeg_command = Command::new("ffmpeg") + .arg("-i") + .arg(youtube_url) + .args(duration_opts) + .args(&[ + "-ac", "2", + "-ar", "48000", + "-f", "opus", + "-acodec", "libopus", + "-b:a", "96k", + "-fs", "5M", + "-", + ]) + .stdout(Stdio::piped()) + .stderr(Stdio::null()) + .stdin(Stdio::null()) + .spawn()?; + + let mut audio_reader = ffmpeg_command.stdout.unwrap(); + + let text = args.rest().to_owned(); + let text = if text.is_empty() { None } else { Some(text) }; + + let conn = connection()?; + + let image = msg.attachments.first() + .ok_or(::failure::err_msg("no attachment")) + .and_then(|att| { + let data = att.download()?; + Image::create(&conn, &att.filename, data, msg.author.id.0) + }) + .ok(); + + let mut audio_data = Vec::new(); + let bytes = audio_reader.read_to_end(&mut audio_data)?; + + if bytes == 0 { + debug!("read 0 bytes from audio reader"); + return send(msg.channel_id, "🔇🔇🔇🔕🔕🔕🔕🔕🔇🔕🔕🔇🔕🔕📣📢📣📢📣", msg.tts); + } + + let audio_id = Audio::create(&conn, audio_data, msg.author.id.0)?; + + let save_result = NewMeme { + title, + content: text, + image_id: image, + audio_id: Some(audio_id), + metadata_id: 0, + }.save(&conn, msg.author.id.0).map(|_| {}); + + use diesel::result::DatabaseErrorKind; + match save_result { + Ok(_) => msg.react("👌"), + Err(e) => { + if let Some(DieselError::DatabaseError(DatabaseErrorKind::UniqueViolation, _)) = e.downcast_ref::() { + error!("tried to create meme that already exists"); + msg.react("❌")?; + return send(msg.channel_id, "that meme already exists", msg.tts); + } + + return Err(e); + } + } +} -- cgit v1.3.1