use super::super::prelude::*; use rusqlite::params; use rand::{seq::SliceRandom, thread_rng}; use serenity::prelude::*; use serenity::voice::LockedAudio; use serenity::{ framework::standard::{macros::command, Args, CommandResult}, model::channel::Message, }; use utilities::prelude::*; #[command] fn play(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { if let Err(err) = channel_contains_author(ctx, msg) { msg.channel_id.say(&ctx.http, err)?; return Ok(()); } let mut data = ctx.data.write(); let media = match data.get_mut::() { Some(media) => media, None => { msg.channel_id.say(&ctx.http, "could not find media data")?; return Ok(()); } }; let mut media_lock = media.lock().unwrap(); if args.len() == 0 { if !check_for_continue(media_lock.song_mut()) { msg.channel_id .say(&ctx.http, "Must provide a URL to a video or audio")?; } } else { let first_arg = args.current().unwrap(); if first_arg == "--local" { handle_local_request(&mut media_lock, ctx, msg)?; } else if first_arg.starts_with("http") { handle_http_request(&mut media_lock, ctx, msg, first_arg)?; } else { let mut arg_list = args.single::()?; for arg in args.iter::() { arg_list += &format!(" {}", arg?.trim()); } handle_song_request(&mut media_lock, ctx, msg, &arg_list)? } } Ok(()) } fn check_for_continue(song_lock: &Option) -> bool { match song_lock { Some(song) => { let song_clone = song.clone(); let mut audio_lock = song_clone.lock(); audio_lock.play(); true } None => false, } } fn append_songs( media: &mut MediaData, ctx: &Context, msg: &Message, mut source: Vec, ) -> VerboseResult<()> { media.playlist_mut().append(&mut source); println!("start playing"); MediaData::start_playing(ctx, media, msg)?; Ok(()) } fn handle_http_request( media: &mut MediaData, ctx: &serenity::client::Context, msg: &serenity::model::channel::Message, url: &str, ) -> VerboseResult<()> { let mut names = Vec::new(); { let sql = media.db(); let mut stmt = match sql.prepare("SELECT name FROM Vulva3 WHERE link = ?") { Ok(statement) => statement, Err(_) => create_error!("failed preparing data base access"), }; let rows = match stmt.query_map(&[url], |row| row.get(0) as rusqlite::Result) { Ok(rows) => rows, Err(_) => create_error!("failed querying rows"), }; for name_result in rows { let name = match name_result { Ok(name) => name, Err(_) => create_error!("failed getting name from row"), }; names.push(name); } } if names.len() > 0 { msg.channel_id .say(&ctx.http, "song already loaded!") .map_err(|err| format!("{}", err))?; append_songs( media, ctx, msg, names.iter().map(|n| Song { name: n.clone() }).collect(), )?; } else { let source = match youtube_dl(&url) { Ok(source) => source, Err(why) => { println!("Err starting source: {:?}", why); msg.channel_id .say(&ctx.http, format!("Error using youtube-dl: {}", why)) .map_err(|err| format!("{}", err))?; return Ok(()); } }; let mut info = if source.len() == 1 { "Finished downloading song:".to_string() } else { "Finished downloading songs:".to_string() }; { let sql = media.db(); for song in &source { info = format!("{}\n\t{}", info, song.name); if sql .execute( "INSERT INTO Vulva3 (name, link) VALUES (?1, ?2)", params![song.name, url], ) .is_err() { create_error!("failed inserting songs into db"); } } } msg.channel_id .say(&ctx.http, info) .map_err(|err| format!("{}", err))?; append_songs(media, ctx, msg, source)?; } Ok(()) } fn handle_local_request( media: &mut MediaData, ctx: &serenity::client::Context, msg: &serenity::model::channel::Message, ) -> VerboseResult<()> { let mut songs = Vec::new(); { let sql = media.db(); let mut stmt = match sql.prepare("SELECT name FROM Vulva3") { Ok(statement) => statement, Err(_) => create_error!("failed preparing data base access"), }; let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result) { Ok(rows) => rows, Err(_) => create_error!("failed querying rows"), }; for name_result in rows { let name = match name_result { Ok(name) => name, Err(_) => create_error!("failed getting name from row"), }; songs.push(Song { name }); } } let mut rng = thread_rng(); songs.shuffle(&mut rng); append_songs(media, ctx, msg, songs)?; Ok(()) } fn handle_song_request( media: &mut MediaData, ctx: &serenity::client::Context, msg: &serenity::model::channel::Message, pattern: &str, ) -> VerboseResult<()> { println!("song request ({})", pattern); let mut songs = Vec::new(); { let sql = media.db(); let mut stmt = match sql.prepare(&format!( "SELECT name FROM Vulva3 WHERE name LIKE '%{}%'", pattern )) { Ok(statement) => statement, Err(_) => create_error!("failed preparing data base access"), }; let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result) { Ok(rows) => rows, Err(_) => create_error!("failed querying rows"), }; for name_result in rows { let name = match name_result { Ok(name) => name, Err(_) => create_error!("failed getting name from row"), }; songs.push(Song { name }); } } println!("{:?}", &songs); if !songs.is_empty() { let mut rng = thread_rng(); songs.shuffle(&mut rng); println!("append songs"); append_songs(media, ctx, msg, songs)?; } else { msg.channel_id .say(&ctx.http, format!("no song found with pattern {}", pattern)) .map_err(|err| format!("{}", err))?; } Ok(()) }