use serenity; use serenity::model::channel::Message; use serenity::prelude::*; use serenity::voice::ffmpeg; use serenity::voice::LockedAudio; use serenity::client::bridge::voice::ClientVoiceManager; use serenity::prelude::Mutex; use std::sync::Arc; use super::prelude::*; use rusqlite::{params, Connection}; use utilities::prelude::*; pub struct Song { pub name: String, } pub struct MediaData { playlist: Vec, current_song: Option, song_name: String, pub next_callback: Option ()>>, sql_data_base: Connection, pub voice_manager: Arc>, } impl MediaData { pub fn new( file: &str, voice_manager: Arc>, ) -> Result { let connection = match Connection::open(file) { Ok(file) => file, Err(_) => return Err(format!("can't open {}", file)), }; match connection.execute( "CREATE TABLE IF NOT EXISTS Vulva3 ( name TEXT PRIMARY KEY, link TEXT NOT NULL )", params![], ) { Ok(_) => (), Err(err) => { println!("{}", err); return Err(format!("can't create table")); } }; Ok(MediaData { playlist: Vec::new(), current_song: None, song_name: String::new(), next_callback: None, sql_data_base: connection, voice_manager, }) } pub fn reset( &mut self, ctx: &serenity::client::Context, msg: &serenity::model::channel::Message, ) -> Result<(), String> { self.playlist.clear(); self.current_song = None; self.song_name = String::new(); self.next_callback = None; if let Some(media) = ctx.data.read().get::() { let mut manager = media.voice_manager.lock(); let guild_id = guild_id(ctx, msg)?; { let handler = match handler(guild_id, &mut manager) { Some(handler) => handler, None => return Ok(()), }; println!("stopped handler"); handler.stop(); } manager.remove(guild_id); } Ok(()) } pub fn db(&self) -> &Connection { &self.sql_data_base } pub fn song(&self) -> &Option { &self.current_song } pub fn song_mut(&mut self) -> &mut Option { &mut self.current_song } pub fn playlist(&self) -> &Vec { &self.playlist } pub fn playlist_mut(&mut self) -> &mut Vec { &mut self.playlist } pub fn song_name(&self) -> &String { &self.song_name } pub fn song_name_mut(&mut self) -> &mut String { &mut self.song_name } pub fn start_playing( ctx: &Context, mediadata: &mut MediaData, msg: &Message, ) -> VerboseResult<()> { // check if there is already playing let already_started = mediadata.song().is_some(); // if there isnt already a song playing, start a new one if !already_started { Self::next_song(ctx, mediadata, msg)?; } Ok(()) } pub fn next_song(ctx: &Context, mediadata: &mut MediaData, msg: &Message) -> VerboseResult<()> { let voice_manager = mediadata.voice_manager.clone(); let mut manager = voice_manager.lock(); let guild_id = guild_id(ctx, msg)?; let mut need_to_leave = false; { let handler = { match handler(guild_id, &mut manager) { Some(handler) => handler, None => { create_error!("error getting handler"); } } }; if mediadata.playlist().is_empty() { need_to_leave = true; handler.stop(); *mediadata.song_mut() = None; *mediadata.song_name_mut() = String::new(); } else { handler.stop(); let first = mediadata.playlist_mut().remove(0); let source = match ffmpeg(first.name.clone()) { Ok(mpeg) => mpeg, Err(_) => { mediadata.playlist_mut().clear(); return Ok(()); } }; *mediadata.song_mut() = Some(handler.play_returning(source)); *mediadata.song_name_mut() = first.name.clone(); msg.channel_id .say(&ctx.http, format!("Playing song: {}", first.name)) .map_err(|err| format!("{}", err))?; } } if need_to_leave { manager.remove(guild_id); } Ok(()) } } unsafe impl Send for MediaData {} unsafe impl Sync for MediaData {} pub struct Media; impl TypeMapKey for Media { type Value = MediaData; }