diff --git a/Cargo.toml b/Cargo.toml index 405c66d..68a30db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,5 @@ serde_json = "*" rand = "0.6" rusqlite = { version = "*", features = ["bundled"] } serenity = { version = "0.6", default-features = false, features = [ "builder", "cache", "client", "framework", "gateway", "model", "standard_framework", "utils", "voice", "rustls_backend"]} -parking_lot = { version = "*" } +lock_api = "0.2.0" +parking_lot = "*" diff --git a/Gopnik McBlyat - Polski Rave b/Gopnik McBlyat - Polski Rave new file mode 100644 index 0000000..fd7668a Binary files /dev/null and b/Gopnik McBlyat - Polski Rave differ diff --git a/Penis1 b/Penis1 new file mode 100644 index 0000000..5ef5846 Binary files /dev/null and b/Penis1 differ diff --git a/src/macros.rs b/src/macros.rs index 3ded82a..a14e0b9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -25,6 +25,20 @@ macro_rules! check_result_return { }; } +/// check result macro, where the Ok() is the type which should be returned, else print error and return +#[macro_export] +macro_rules! check_result_return_ok { + ($v:expr) => { + match $v { + Ok(t) => t, + Err(msg) => { + println!("{}", msg); + return Ok(()); + } + } + }; +} + // check result macro, where the Ok() is void #[macro_export] macro_rules! check_error { @@ -46,6 +60,17 @@ macro_rules! display_error { }; } +/// check result macro, where the Ok() is void, but just print the error message +#[macro_export] +macro_rules! display_error_ok { + ($v:expr) => { + if let Err(msg) = $v { + println!("{}", msg); + return Ok(()); + }; + }; +} + macro_rules! print_error { ($v:expr) => { if let Err(msg) = $v { diff --git a/src/main.rs b/src/main.rs index 6882230..35269d8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,7 @@ use std::sync::Arc; use confighandler::*; use player::prelude::*; +use std::collections::HashSet; struct Config { token: String, @@ -51,7 +52,7 @@ impl Default for Config { group!({ name: "general", options: {}, - commands: [ip] + commands: [ip, list, pause, play, remove, skip, stop] }); fn main() { @@ -95,10 +96,36 @@ fn main() { { let mut data = client.data.write(); data.insert::(Arc::clone(&client.voice_manager)); + data.insert::(MediaData::new("Penis1").expect("failed to create media data handle")); } - let media_data = - Arc::new(MediaData::new("Penis1").expect("failed to create media data handle")); + // We will fetch your bot's owners and id + let (owners, bot_id) = match client.cache_and_http.http.get_current_application_info() { + Ok(info) => { + let mut owners = HashSet::new(); + owners.insert(info.owner.id); + + (owners, info.id) + } + Err(why) => panic!("Could not access application info: {:?}", why), + }; + + client.with_framework( + // Configures the client, allowing for options to mutate how the + // framework functions. + // + // Refer to the documentation for + // `serenity::ext::framework::Configuration` for all available + // configurations. + StandardFramework::new() + .configure(|c| { + c.with_whitespace(true) + .on_mention(Some(bot_id)) + .prefix(&config.prefix) + .owners(owners) + }) + .group(&GENERAL_GROUP), + ); /* @@ -129,10 +156,9 @@ fn main() { .cmd("ip", IP::new()) .cmd("remove", Remove::new(media_data.clone())), ); + */ let _ = client .start() .map_err(|why| println!("Client ended: {:?}", why)); - - */ } diff --git a/src/player/commands/ip.rs b/src/player/commands/ip.rs index 7951251..b0e47e9 100644 --- a/src/player/commands/ip.rs +++ b/src/player/commands/ip.rs @@ -10,7 +10,7 @@ use std::process::{Command, Stdio}; use std::str::from_utf8; #[command] -fn ip(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult { +fn ip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { let args = ["ifconfig.me"]; let out = match Command::new("curl") @@ -27,8 +27,8 @@ fn ip(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult { } match from_utf8(out.stdout.as_slice()) { - Ok(string) => print_error!(msg.author.direct_message(|m| m.content(string))), - Err(_) => print_error!(msg.channel_id.say("error getting IP string")), + Ok(string) => print_error!(msg.author.direct_message(&ctx, |m| m.content(string))), + Err(_) => print_error!(msg.channel_id.say(&ctx.http, "error getting IP string")), }; Ok(()) diff --git a/src/player/commands/list.rs b/src/player/commands/list.rs index 853dff3..73837ee 100644 --- a/src/player/commands/list.rs +++ b/src/player/commands/list.rs @@ -19,10 +19,10 @@ fn list(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { let mut output = String::new(); let data = ctx.data.read(); - let media = match data.get::() { - Ok(media) => media, - Err(_) => { - msg.channel_id.say("could not find media data"); + let media = match data.get::() { + Some(media) => media, + None => { + display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data")); return Ok(()); } }; @@ -46,7 +46,7 @@ fn list(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { } } - print_error!(msg.channel_id.say(output)); + print_error!(msg.channel_id.say(&ctx.http, output)); Ok(()) } diff --git a/src/player/commands/pause.rs b/src/player/commands/pause.rs index c6db390..0afb3f5 100644 --- a/src/player/commands/pause.rs +++ b/src/player/commands/pause.rs @@ -19,15 +19,18 @@ fn pause(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { } let data = ctx.data.read(); - let media = match data.get::() { - Ok(media) => media, - Err(_) => { - msg.channel_id.say("could not find media data"); + let media = match data.get::() { + Some(media) => media, + None => { + display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data")); return Ok(()); } }; - media.song().pause(); + if let Some(song) = media.song() { + let mut lock = song.lock(); + lock.pause(); + } Ok(()) } diff --git a/src/player/commands/play.rs b/src/player/commands/play.rs index 1cd7bf5..498c05d 100644 --- a/src/player/commands/play.rs +++ b/src/player/commands/play.rs @@ -1,8 +1,6 @@ -use parking_lot; +use lock_api::RawMutex; -use std::cell::RefCell; -use std::ops::{Deref, DerefMut}; -use std::sync::{Arc, MutexGuard}; +use std::sync::Arc; use rand::{seq::SliceRandom, thread_rng}; @@ -18,7 +16,7 @@ use serenity::{ }; #[command] -fn play(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult { +fn play(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult { if !channel_contains_author(ctx, msg) { println!( "user {} is not in the same voice channel as the bot", @@ -27,18 +25,20 @@ fn play(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult { return Ok(()); } - let data = ctx.data.read(); - let mut media = match data.get_mut::() { - Ok(media) => media, - Err(_) => { - msg.channel_id.say("could not find media data"); + let mut data = ctx.data.write(); + let media = match data.get_mut::() { + Some(media) => media, + None => { + display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data")); return Ok(()); } }; if args.len() == 0 { - if !Self::check_for_continue(self.media.song_mut()?) { - print_error!(msg.channel_id.say("Must provide a URL to a video or audio")); + if !check_for_continue(media.song_mut()) { + print_error!(msg + .channel_id + .say(&ctx.http, "Must provide a URL to a video or audio")); } } else if args.len() == 1 { let arg = match args.single::() { @@ -48,21 +48,21 @@ fn play(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult { }; if arg == "--local" { - self.handle_local_request(ctx, msg)?; + handle_local_request(media, ctx, msg)?; } else if arg.starts_with("http") { - self.handle_http_request(ctx, msg, &arg)?; + handle_http_request(media, ctx, msg, &arg)?; } else { - self.handle_song_request(ctx, msg, &arg)?; + handle_song_request(media, ctx, msg, &arg)?; } } else { - print_error!(msg.channel_id.say("Unsupported argument list")); + print_error!(msg.channel_id.say(&ctx.http, "Unsupported argument list")); } Ok(()) } -fn check_for_continue(song_lock: MutexGuard>>) -> bool { - match song_lock.borrow_mut().deref_mut() { +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(); @@ -74,20 +74,13 @@ fn check_for_continue(song_lock: MutexGuard>>) -> bo } } -fn check_join_channel( - manager_lock: &Arc>, - msg: &serenity::model::channel::Message, +fn check_join_channel( + manager_lock: &Arc>, + ctx: &Context, + msg: &Message, ) { - let guild = match msg.guild() { - Some(guild) => guild, - None => { - display_error!(msg.channel_id.say("Groups and DMs not supported")); - - return; - } - }; - - let guild_id = guild.read().id; + let guild = check_result_return!(guild(ctx, msg)); + let guild_id = check_result_return!(guild_id(ctx, msg)); let channel_id = guild .read() @@ -98,50 +91,45 @@ fn check_join_channel( let connect_to = match channel_id { Some(channel) => channel, None => { - display_error!(msg.reply("Not in a voice channel")); + display_error!(msg.reply(ctx, "Not in a voice channel")); return; } }; let mut manager = manager_lock.lock(); - manager.join(guild_id, connect_to); } fn append_songs( media: &mut MediaData, - ctx: &mut serenity::client::Context, - msg: &serenity::model::channel::Message, + ctx: &Context, + msg: &Message, mut source: Vec, ) -> Result<(), String> { - { - let playlist_mutex = self.media.playlist_mut()?; - playlist_mutex.borrow_mut().append(&mut source); - } + media.playlist_mut().append(&mut source); - if let Some(manager_lock) = ctx.data.lock().get::().cloned() { - Self::check_join_channel(&manager_lock, msg); + if let Some(manager_lock) = ctx.data.read().get::().cloned() { + check_join_channel(&manager_lock, ctx, msg); - let check_finished = { - let media_clone = self.media.clone(); - let channel_id = msg.channel_id; - let manager_lock_clone = manager_lock.clone(); + // let check_finished = { + // let channel_id = msg.channel_id; + // let manager_lock_clone = manager_lock.clone(); - Arc::new(move || { - let callback = match media_clone.next_callback.borrow().deref() { - Some(callback) => callback.clone(), - None => { - println!("next_callback not set!"); - return; - } - }; + // Arc::new(move || { + // let callback = match media.next_callback.borrow().deref() { + // Some(callback) => callback.clone(), + // None => { + // println!("next_callback not set!"); + // return; + // } + // }; - MediaData::next_song(&media_clone, channel_id, &manager_lock_clone, callback); - }) - }; + // MediaData::next_song(&media_clone, channel_id, &manager_lock_clone, callback); + // }) + // }; - MediaData::start_playing(&self.media, check_finished, msg.channel_id, &manager_lock); + MediaData::start_playing(ctx, media, msg, &manager_lock); } Ok(()) @@ -149,160 +137,172 @@ fn append_songs( fn handle_http_request( media: &mut MediaData, - ctx: &mut serenity::client::Context, + ctx: &serenity::client::Context, msg: &serenity::model::channel::Message, url: &String, ) -> Result<(), String> { - let sql = self.media.lock_db()?; - - let mut stmt = match sql.prepare("SELECT name FROM Vulva3 WHERE link = ?") { - Ok(statement) => statement, - Err(_) => return Err("failed preparing data base access".to_string()), - }; - - let rows = match stmt.query_map(&[url], |row| row.get(0) as rusqlite::Result) { - Ok(rows) => rows, - Err(_) => return Err("failed querying rows".to_string()), - }; - let mut names = Vec::new(); - for name_result in rows { - let name = match name_result { - Ok(name) => name, - Err(_) => return Err("failed getting name from row".to_string()), + + { + let sql = media.db(); + + let mut stmt = match sql.prepare("SELECT name FROM Vulva3 WHERE link = ?") { + Ok(statement) => statement, + Err(_) => return Err("failed preparing data base access".to_string()), }; - names.push(name); + let rows = match stmt.query_map(&[url], |row| row.get(0) as rusqlite::Result) { + Ok(rows) => rows, + Err(_) => return Err("failed querying rows".to_string()), + }; + + for name_result in rows { + let name = match name_result { + Ok(name) => name, + Err(_) => return Err("failed getting name from row".to_string()), + }; + + names.push(name); + } } if names.len() > 0 { - print_error!(msg.channel_id.say("song already loaded!")); + print_error!(msg.channel_id.say(&ctx.http, "song already loaded!")); - self.append_songs( + append_songs( + media, ctx, msg, names.iter().map(|n| Song { name: n.clone() }).collect(), )?; - - return Ok(()); - } - - let source = match youtube_dl(&url) { - Ok(source) => source, - Err(why) => { - println!("Err starting source: {:?}", why); - - print_error!(msg - .channel_id - .say(format!("Error using youtube-dl: {}", why))); - - return Ok(()); - } - }; - - let mut info = if source.len() == 1 { - "Finished downloading song:".to_string() } else { - "Finished downloading songs:".to_string() - }; + let source = match youtube_dl(&url) { + Ok(source) => source, + Err(why) => { + println!("Err starting source: {:?}", why); - for song in &source { - info = format!("{}\n\t{}", info, song.name); + print_error!(msg + .channel_id + .say(&ctx.http, format!("Error using youtube-dl: {}", why))); + + return Ok(()); + } + }; + + let mut info = if source.len() == 1 { + "Finished downloading song:".to_string() + } else { + "Finished downloading songs:".to_string() + }; - if sql - .execute( - "INSERT INTO Vulva3 (name, link) - VALUES (?1, ?2)", - params![song.name, url], - ) - .is_err() { - return Err("failed inserting songs into db".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() + { + return Err("failed inserting songs into db".to_string()); + } + } } + + print_error!(msg.channel_id.say(&ctx.http, info)); + + append_songs(media, ctx, msg, source)?; } - print_error!(msg.channel_id.say(info)); - - self.append_songs(ctx, msg, source)?; - Ok(()) } fn handle_local_request( media: &mut MediaData, - ctx: &mut serenity::client::Context, + ctx: &serenity::client::Context, msg: &serenity::model::channel::Message, ) -> Result<(), String> { - let sql = self.media.lock_db()?; - - let mut stmt = match sql.prepare("SELECT name FROM Vulva3") { - Ok(statement) => statement, - Err(_) => return Err("failed preparing data base access".to_string()), - }; - - let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result) { - Ok(rows) => rows, - Err(_) => return Err("failed querying rows".to_string()), - }; - let mut songs = Vec::new(); - for name_result in rows { - let name = match name_result { - Ok(name) => name, - Err(_) => return Err("failed getting name from row".to_string()), + + { + let sql = media.db(); + + let mut stmt = match sql.prepare("SELECT name FROM Vulva3") { + Ok(statement) => statement, + Err(_) => return Err("failed preparing data base access".to_string()), }; - songs.push(Song { name }); + let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result) { + Ok(rows) => rows, + Err(_) => return Err("failed querying rows".to_string()), + }; + + for name_result in rows { + let name = match name_result { + Ok(name) => name, + Err(_) => return Err("failed getting name from row".to_string()), + }; + + songs.push(Song { name }); + } } let mut rng = thread_rng(); songs.shuffle(&mut rng); - self.append_songs(ctx, msg, songs)?; + append_songs(media, ctx, msg, songs)?; Ok(()) } fn handle_song_request( media: &mut MediaData, - ctx: &mut serenity::client::Context, + ctx: &serenity::client::Context, msg: &serenity::model::channel::Message, pattern: &str, ) -> Result<(), String> { - let sql = self.media.lock_db()?; - - let mut stmt = match sql.prepare(&format!( - "SELECT name FROM Vulva3 WHERE name LIKE '%{}%'", - pattern - )) { - Ok(statement) => statement, - Err(_) => return Err("failed preparing data base access".to_string()), - }; - - let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result) { - Ok(rows) => rows, - Err(_) => return Err("failed querying rows".to_string()), - }; - let mut songs = Vec::new(); - for name_result in rows { - let name = match name_result { - Ok(name) => name, - Err(_) => return Err("failed getting name from row".to_string()), + + { + let sql = media.db(); + + let mut stmt = match sql.prepare(&format!( + "SELECT name FROM Vulva3 WHERE name LIKE '%{}%'", + pattern + )) { + Ok(statement) => statement, + Err(_) => return Err("failed preparing data base access".to_string()), }; - songs.push(Song { name }); + let rows = match stmt.query_map(params![], |row| row.get(0) as rusqlite::Result) { + Ok(rows) => rows, + Err(_) => return Err("failed querying rows".to_string()), + }; + + for name_result in rows { + let name = match name_result { + Ok(name) => name, + Err(_) => return Err("failed getting name from row".to_string()), + }; + + songs.push(Song { name }); + } } if !songs.is_empty() { let mut rng = thread_rng(); songs.shuffle(&mut rng); - self.append_songs(ctx, msg, songs)?; + append_songs(media, ctx, msg, songs)?; } else { print_error!(msg .channel_id - .say(format!("no song found with pattern {}", pattern))); + .say(&ctx.http, format!("no song found with pattern {}", pattern))); } Ok(()) diff --git a/src/player/commands/remove.rs b/src/player/commands/remove.rs index 44e096c..cafec6f 100644 --- a/src/player/commands/remove.rs +++ b/src/player/commands/remove.rs @@ -15,10 +15,10 @@ use serenity::{ #[command] fn remove(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { let data = ctx.data.read(); - let media = match data.get::() { - Ok(media) => media, - Err(_) => { - msg.channel_id.say("could not find media data"); + let media = match data.get::() { + Some(media) => media, + None => { + display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data")); return Ok(()); } }; @@ -34,15 +34,14 @@ fn remove(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { if !song_name.is_empty() { match fs::remove_file(&song_name) { - Ok(_) => print_error!(msg.channel_id.say(format!( - "Remove current song ({}) from local disk", - song_name - ))), - Err(err) => print_error!(msg.channel_id.say(format!( - "Error removing file ({}): {:?}", - song_name, - err.kind() - ))), + Ok(_) => print_error!(msg.channel_id.say( + &ctx.http, + format!("Remove current song ({}) from local disk", song_name) + )), + Err(err) => print_error!(msg.channel_id.say( + &ctx.http, + format!("Error removing file ({}): {:?}", song_name, err.kind()) + )), }; } diff --git a/src/player/commands/skip.rs b/src/player/commands/skip.rs index bb68b95..e082273 100644 --- a/src/player/commands/skip.rs +++ b/src/player/commands/skip.rs @@ -19,42 +19,32 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { return Ok(()); } - if let Some(mut manager_lock) = ctx.data.lock().get::().cloned() { + let mut data = ctx.data.write(); + + if let Some(manager_lock) = data.get_mut::().cloned() { let mut manager = manager_lock.lock(); - let guild_id = match guild_id(msg.channel_id) { - Some(id) => id, - None => { - println!("error getting guild id"); - print_error!(msg.channel_id.say("error getting guild id")); - - return Ok(()); - } - }; + let guild_id = check_result_return_ok!(guild_id(ctx, msg)); if let Some(handler) = handler(guild_id, &mut manager) { - let data = ctx.data.read(); - let mut media = match data.get_mut::() { - Ok(media) => media, - Err(_) => { - msg.channel_id.say("could not find media data"); + let media = match data.get_mut::() { + Some(media) => media, + None => { + display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data")); return Ok(()); } }; - let mut playlist = media.playlist_mut(); - let mut song = media.song_mut(); - // if current song is the last song in this playlist, just return - if playlist.is_empty() { + if media.playlist().is_empty() { print_error!(msg .channel_id - .say("playlist is empty, no next song available")); + .say(&ctx.http, "playlist is empty, no next song available")); return Ok(()); } else { // remove the current song from the playlist - let first = playlist.remove(0); + let first = media.playlist_mut().remove(0); // stop the current song from playing handler.stop(); @@ -63,8 +53,8 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { let source = match ffmpeg(first.name.clone()) { Ok(mpeg) => mpeg, Err(_) => { - playlist.clear(); - *song = None; + media.playlist_mut().clear(); + *media.song_mut() = None; return Ok(()); } @@ -85,12 +75,13 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { None => println!("error getting callback from media"), } */ - *song = Some(handler.play_returning(source)); + *media.song_mut() = Some(handler.play_returning(source)); *media.song_name_mut() = first.name.clone(); - print_error!(msg - .channel_id - .say(format!("Skipped current song, now playing: {}", first.name))); + print_error!(msg.channel_id.say( + &ctx.http, + format!("Skipped current song, now playing: {}", first.name) + )); } } } diff --git a/src/player/commands/stop.rs b/src/player/commands/stop.rs index 2e79312..33cc5a7 100644 --- a/src/player/commands/stop.rs +++ b/src/player/commands/stop.rs @@ -16,16 +16,16 @@ fn stop(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { return Ok(()); } - let data = ctx.data.read(); - let mut media = match data.get_mut::() { - Ok(media) => media, - Err(_) => { - msg.channel_id.say("could not find media data"); + let mut data = ctx.data.write(); + let media = match data.get_mut::() { + Some(media) => media, + None => { + display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data")); return Ok(()); } }; - print_error!(data.reset(ctx, msg)); + print_error!(media.reset(ctx, msg)); Ok(()) } diff --git a/src/player/mediadata.rs b/src/player/mediadata.rs index 1e75574..1879f3b 100644 --- a/src/player/mediadata.rs +++ b/src/player/mediadata.rs @@ -1,5 +1,6 @@ use serenity; -use serenity::model::id::ChannelId; +use serenity::model::channel::Message; +use serenity::prelude::*; use serenity::voice::ffmpeg; use serenity::voice::LockedAudio; @@ -55,21 +56,18 @@ impl MediaData { pub fn reset( &mut self, - ctx: &mut serenity::client::Context, + ctx: &serenity::client::Context, msg: &serenity::model::channel::Message, ) -> Result<(), String> { - self.playlist().clear(); - self.song = None; - self.name = String::new(); - self.next_callback = None(); + self.playlist.clear(); + self.current_song = None; + self.song_name = String::new(); + self.next_callback = None; - if let Some(manager_lock) = ctx.data.lock().get::().cloned() { + if let Some(manager_lock) = ctx.data.read().get::().cloned() { let mut manager = manager_lock.lock(); - let guild_id = match guild_id(msg.channel_id) { - Some(guild_id) => guild_id, - None => return Ok(()), - }; + let guild_id = guild_id(ctx, msg)?; { let handler = match handler(guild_id, &mut manager) { @@ -109,60 +107,41 @@ impl MediaData { } pub fn song_name(&self) -> &String { - &self.name + &self.song_name } pub fn song_name_mut(&mut self) -> &mut String { - &mut self.name + &mut self.song_name } pub fn start_playing( - mediadata: &Arc, - callback: Arc ()>, - channel_id: ChannelId, + ctx: &Context, + mediadata: &mut MediaData, + msg: &Message, manager_lock: &Arc< serenity::prelude::Mutex, >, ) { // check if there is already playing - let already_started = { - let song_lock = match mediadata.song_mut() { - Ok(song) => song, - Err(msg) => { - println!("{}", msg); - return; - } - }; - - let song = song_lock.borrow(); - song.is_some() - }; + let already_started = { mediadata.song().is_some() }; // if there isnt already a song playing, start a new one if !already_started { - *mediadata.next_callback.borrow_mut() = Some(callback.clone()); - - Self::next_song(mediadata, channel_id, manager_lock, callback); + Self::next_song(ctx, mediadata, msg, manager_lock); } } pub fn next_song( - mediadata: &Arc, - channel_id: ChannelId, + ctx: &Context, + mediadata: &mut MediaData, + msg: &Message, manager_lock: &Arc< serenity::prelude::Mutex, >, - callback: Arc ()>, ) { let mut manager = manager_lock.lock(); - let guild_id = match guild_id(channel_id) { - Some(id) => id, - None => { - println!("error getting guild_id"); - return; - } - }; + let guild_id = check_result_return!(guild_id(ctx, msg)); let mut need_to_leave = false; @@ -177,56 +156,31 @@ impl MediaData { } }; - let playlist_lock = match mediadata.playlist_mut() { - Ok(playlist) => playlist, - Err(msg) => { - println!("{}", msg); - return; - } - }; - let mut playlist = playlist_lock.borrow_mut(); - - let song_name_lock = match mediadata.name_mut() { - Ok(name) => name, - Err(msg) => { - println!("{}", msg); - return; - } - }; - let mut name = song_name_lock.borrow_mut(); - - let song_lock = match mediadata.song_mut() { - Ok(song) => song, - Err(msg) => { - println!("{}", msg); - return; - } - }; - let mut song = song_lock.borrow_mut(); - - if playlist.is_empty() { + if mediadata.playlist().is_empty() { need_to_leave = true; handler.stop(); - *song = None; - *name = String::new(); + *mediadata.song_mut() = None; + *mediadata.song_name_mut() = String::new(); } else { handler.stop(); - let first = playlist.remove(0); + let first = mediadata.playlist_mut().remove(0); let source = match ffmpeg(first.name.clone()) { Ok(mpeg) => mpeg, Err(_) => { - playlist.clear(); + mediadata.playlist_mut().clear(); return; } }; - *song = Some(handler.play_returning_and_callback(source, callback)); - *name = first.name.clone(); + *mediadata.song_mut() = Some(handler.play_returning(source)); + *mediadata.song_name_mut() = first.name.clone(); - print_error!(channel_id.say(format!("Playing song: {}", first.name))); + print_error!(msg + .channel_id + .say(&ctx.http, format!("Playing song: {}", first.name))); } } @@ -238,3 +192,9 @@ impl MediaData { unsafe impl Send for MediaData {} unsafe impl Sync for MediaData {} + +pub struct Media; + +impl TypeMapKey for Media { + type Value = MediaData; +} diff --git a/src/player/player.rs b/src/player/player.rs index 974c981..c25e24e 100644 --- a/src/player/player.rs +++ b/src/player/player.rs @@ -1,26 +1,43 @@ -use parking_lot::MutexGuard; +use lock_api::{MutexGuard, RawMutex}; use serenity; -use serenity::model::id::{ChannelId, GuildId}; +use serenity::model::channel::Message; +use serenity::model::guild::Guild; +use serenity::model::id::GuildId; +use serenity::prelude::RwLock as SerRwLock; use serenity::voice::Handler; +use std::sync::Arc; + +// This imports `typemap`'s `Key` as `TypeMapKey`. +use serenity::prelude::*; + use super::prelude::*; -pub fn guild_id(channel_id: ChannelId) -> Option { - /* - match CACHE.read().guild_channel(channel_id) { - Some(channel) => Some(channel.read().guild_id), +pub fn guild(ctx: &Context, msg: &Message) -> Result>, String> { + match msg.guild(&ctx.cache) { + Some(guild) => Ok(guild), None => { - print_error!(channel_id.say("Error finding channel info")); - None + if msg + .channel_id + .say(&ctx.http, "Groups and DMs not supported") + .is_err() + {} + + Err("failed getting Guild".to_string()) } } - */ - None } -pub fn handler<'a>( +pub fn guild_id(ctx: &Context, msg: &Message) -> Result { + let guild = guild(ctx, msg)?; + let guild_read = guild.read(); + + Ok(guild_read.id) +} + +pub fn handler<'a, T: RawMutex>( guild_id: GuildId, - manager: &'a mut MutexGuard<'_, serenity::client::bridge::voice::ClientVoiceManager>, + manager: &'a mut MutexGuard<'_, T, serenity::client::bridge::voice::ClientVoiceManager>, ) -> Option<&'a mut Handler> { manager.get_mut(guild_id) } @@ -33,12 +50,9 @@ pub fn channel_contains_author( match ctx.data.read().get::().cloned() { Some(manager_lock) => { let mut manager = manager_lock.lock(); - let guild_id = match guild_id(msg.channel_id) { - Some(guild_id) => guild_id, - None => { - println!("error getting guild_id"); - return true; - } + let guild_id = match guild_id(ctx, msg) { + Ok(id) => id, + Err(_) => return true, }; let handler = match handler(guild_id, &mut manager) { diff --git a/src/player/prelude.rs b/src/player/prelude.rs index cca35ae..a963b14 100644 --- a/src/player/prelude.rs +++ b/src/player/prelude.rs @@ -1,4 +1,4 @@ -pub use super::mediadata::{MediaData, Song}; +pub use super::mediadata::{Media, MediaData, Song}; pub use super::commands::ip::*; pub use super::commands::list::*; @@ -13,4 +13,4 @@ pub use super::voicemanager::VoiceManager; pub use super::youtube::youtube_dl; -pub use super::player::{channel_contains_author, guild_id, handler}; +pub use super::player::{channel_contains_author, guild, guild_id, handler}; diff --git a/src/player/voicemanager.rs b/src/player/voicemanager.rs index 180bcd7..efaf758 100644 --- a/src/player/voicemanager.rs +++ b/src/player/voicemanager.rs @@ -1,5 +1,5 @@ -use parking_lot::Mutex; use serenity::client::bridge::voice::ClientVoiceManager; +use serenity::prelude::Mutex; use std::sync::Arc; use typemap::Key;