Apply serenity 0.6 api

This commit is contained in:
hodasemi 2019-07-12 14:41:51 +02:00
parent 4276428a8b
commit f89c8706eb
16 changed files with 335 additions and 316 deletions

View file

@ -10,4 +10,5 @@ serde_json = "*"
rand = "0.6" rand = "0.6"
rusqlite = { version = "*", features = ["bundled"] } rusqlite = { version = "*", features = ["bundled"] }
serenity = { version = "0.6", default-features = false, features = [ "builder", "cache", "client", "framework", "gateway", "model", "standard_framework", "utils", "voice", "rustls_backend"]} 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 = "*"

Binary file not shown.

BIN
Penis1 Normal file

Binary file not shown.

View file

@ -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 // check result macro, where the Ok() is void
#[macro_export] #[macro_export]
macro_rules! check_error { 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 { macro_rules! print_error {
($v:expr) => { ($v:expr) => {
if let Err(msg) = $v { if let Err(msg) = $v {

View file

@ -33,6 +33,7 @@ use std::sync::Arc;
use confighandler::*; use confighandler::*;
use player::prelude::*; use player::prelude::*;
use std::collections::HashSet;
struct Config { struct Config {
token: String, token: String,
@ -51,7 +52,7 @@ impl Default for Config {
group!({ group!({
name: "general", name: "general",
options: {}, options: {},
commands: [ip] commands: [ip, list, pause, play, remove, skip, stop]
}); });
fn main() { fn main() {
@ -95,10 +96,36 @@ fn main() {
{ {
let mut data = client.data.write(); let mut data = client.data.write();
data.insert::<VoiceManager>(Arc::clone(&client.voice_manager)); data.insert::<VoiceManager>(Arc::clone(&client.voice_manager));
data.insert::<Media>(MediaData::new("Penis1").expect("failed to create media data handle"));
} }
let media_data = // We will fetch your bot's owners and id
Arc::new(MediaData::new("Penis1").expect("failed to create media data handle")); 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("ip", IP::new())
.cmd("remove", Remove::new(media_data.clone())), .cmd("remove", Remove::new(media_data.clone())),
); );
*/
let _ = client let _ = client
.start() .start()
.map_err(|why| println!("Client ended: {:?}", why)); .map_err(|why| println!("Client ended: {:?}", why));
*/
} }

View file

@ -10,7 +10,7 @@ use std::process::{Command, Stdio};
use std::str::from_utf8; use std::str::from_utf8;
#[command] #[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 args = ["ifconfig.me"];
let out = match Command::new("curl") 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()) { match from_utf8(out.stdout.as_slice()) {
Ok(string) => print_error!(msg.author.direct_message(|m| m.content(string))), Ok(string) => print_error!(msg.author.direct_message(&ctx, |m| m.content(string))),
Err(_) => print_error!(msg.channel_id.say("error getting IP string")), Err(_) => print_error!(msg.channel_id.say(&ctx.http, "error getting IP string")),
}; };
Ok(()) Ok(())

View file

@ -19,10 +19,10 @@ fn list(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
let mut output = String::new(); let mut output = String::new();
let data = ctx.data.read(); let data = ctx.data.read();
let media = match data.get::<MediaData>() { let media = match data.get::<Media>() {
Ok(media) => media, Some(media) => media,
Err(_) => { None => {
msg.channel_id.say("could not find media data"); display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
return Ok(()); 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(()) Ok(())
} }

View file

@ -19,15 +19,18 @@ fn pause(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
} }
let data = ctx.data.read(); let data = ctx.data.read();
let media = match data.get::<MediaData>() { let media = match data.get::<Media>() {
Ok(media) => media, Some(media) => media,
Err(_) => { None => {
msg.channel_id.say("could not find media data"); display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
return Ok(()); return Ok(());
} }
}; };
media.song().pause(); if let Some(song) = media.song() {
let mut lock = song.lock();
lock.pause();
}
Ok(()) Ok(())
} }

View file

@ -1,8 +1,6 @@
use parking_lot; use lock_api::RawMutex;
use std::cell::RefCell; use std::sync::Arc;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, MutexGuard};
use rand::{seq::SliceRandom, thread_rng}; use rand::{seq::SliceRandom, thread_rng};
@ -18,7 +16,7 @@ use serenity::{
}; };
#[command] #[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) { if !channel_contains_author(ctx, msg) {
println!( println!(
"user {} is not in the same voice channel as the bot", "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(()); return Ok(());
} }
let data = ctx.data.read(); let mut data = ctx.data.write();
let mut media = match data.get_mut::<MediaData>() { let media = match data.get_mut::<Media>() {
Ok(media) => media, Some(media) => media,
Err(_) => { None => {
msg.channel_id.say("could not find media data"); display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
return Ok(()); return Ok(());
} }
}; };
if args.len() == 0 { if args.len() == 0 {
if !Self::check_for_continue(self.media.song_mut()?) { if !check_for_continue(media.song_mut()) {
print_error!(msg.channel_id.say("Must provide a URL to a video or audio")); print_error!(msg
.channel_id
.say(&ctx.http, "Must provide a URL to a video or audio"));
} }
} else if args.len() == 1 { } else if args.len() == 1 {
let arg = match args.single::<String>() { let arg = match args.single::<String>() {
@ -48,21 +48,21 @@ fn play(ctx: &mut Context, msg: &Message, args: Args) -> CommandResult {
}; };
if arg == "--local" { if arg == "--local" {
self.handle_local_request(ctx, msg)?; handle_local_request(media, ctx, msg)?;
} else if arg.starts_with("http") { } else if arg.starts_with("http") {
self.handle_http_request(ctx, msg, &arg)?; handle_http_request(media, ctx, msg, &arg)?;
} else { } else {
self.handle_song_request(ctx, msg, &arg)?; handle_song_request(media, ctx, msg, &arg)?;
} }
} else { } else {
print_error!(msg.channel_id.say("Unsupported argument list")); print_error!(msg.channel_id.say(&ctx.http, "Unsupported argument list"));
} }
Ok(()) Ok(())
} }
fn check_for_continue(song_lock: MutexGuard<RefCell<Option<LockedAudio>>>) -> bool { fn check_for_continue(song_lock: &Option<LockedAudio>) -> bool {
match song_lock.borrow_mut().deref_mut() { match song_lock {
Some(song) => { Some(song) => {
let song_clone = song.clone(); let song_clone = song.clone();
let mut audio_lock = song_clone.lock(); let mut audio_lock = song_clone.lock();
@ -74,20 +74,13 @@ fn check_for_continue(song_lock: MutexGuard<RefCell<Option<LockedAudio>>>) -> bo
} }
} }
fn check_join_channel( fn check_join_channel<T: RawMutex>(
manager_lock: &Arc<parking_lot::Mutex<serenity::client::bridge::voice::ClientVoiceManager>>, manager_lock: &Arc<lock_api::Mutex<T, serenity::client::bridge::voice::ClientVoiceManager>>,
msg: &serenity::model::channel::Message, ctx: &Context,
msg: &Message,
) { ) {
let guild = match msg.guild() { let guild = check_result_return!(guild(ctx, msg));
Some(guild) => guild, let guild_id = check_result_return!(guild_id(ctx, msg));
None => {
display_error!(msg.channel_id.say("Groups and DMs not supported"));
return;
}
};
let guild_id = guild.read().id;
let channel_id = guild let channel_id = guild
.read() .read()
@ -98,50 +91,45 @@ fn check_join_channel(
let connect_to = match channel_id { let connect_to = match channel_id {
Some(channel) => channel, Some(channel) => channel,
None => { None => {
display_error!(msg.reply("Not in a voice channel")); display_error!(msg.reply(ctx, "Not in a voice channel"));
return; return;
} }
}; };
let mut manager = manager_lock.lock(); let mut manager = manager_lock.lock();
manager.join(guild_id, connect_to); manager.join(guild_id, connect_to);
} }
fn append_songs( fn append_songs(
media: &mut MediaData, media: &mut MediaData,
ctx: &mut serenity::client::Context, ctx: &Context,
msg: &serenity::model::channel::Message, msg: &Message,
mut source: Vec<Song>, mut source: Vec<Song>,
) -> Result<(), String> { ) -> Result<(), String> {
{ media.playlist_mut().append(&mut source);
let playlist_mutex = self.media.playlist_mut()?;
playlist_mutex.borrow_mut().append(&mut source);
}
if let Some(manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() { if let Some(manager_lock) = ctx.data.read().get::<VoiceManager>().cloned() {
Self::check_join_channel(&manager_lock, msg); check_join_channel(&manager_lock, ctx, msg);
let check_finished = { // let check_finished = {
let media_clone = self.media.clone(); // let channel_id = msg.channel_id;
let channel_id = msg.channel_id; // let manager_lock_clone = manager_lock.clone();
let manager_lock_clone = manager_lock.clone();
Arc::new(move || { // Arc::new(move || {
let callback = match media_clone.next_callback.borrow().deref() { // let callback = match media.next_callback.borrow().deref() {
Some(callback) => callback.clone(), // Some(callback) => callback.clone(),
None => { // None => {
println!("next_callback not set!"); // println!("next_callback not set!");
return; // 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(()) Ok(())
@ -149,160 +137,172 @@ fn append_songs(
fn handle_http_request( fn handle_http_request(
media: &mut MediaData, media: &mut MediaData,
ctx: &mut serenity::client::Context, ctx: &serenity::client::Context,
msg: &serenity::model::channel::Message, msg: &serenity::model::channel::Message,
url: &String, url: &String,
) -> Result<(), 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<String>) {
Ok(rows) => rows,
Err(_) => return Err("failed querying rows".to_string()),
};
let mut names = Vec::new(); let mut names = Vec::new();
for name_result in rows {
let name = match name_result { {
Ok(name) => name, let sql = media.db();
Err(_) => return Err("failed getting name from row".to_string()),
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<String>) {
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 { 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, ctx,
msg, msg,
names.iter().map(|n| Song { name: n.clone() }).collect(), 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 { } 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 { print_error!(msg
info = format!("{}\n\t{}", info, song.name); .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(()) Ok(())
} }
fn handle_local_request( fn handle_local_request(
media: &mut MediaData, media: &mut MediaData,
ctx: &mut serenity::client::Context, ctx: &serenity::client::Context,
msg: &serenity::model::channel::Message, msg: &serenity::model::channel::Message,
) -> Result<(), String> { ) -> 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<String>) {
Ok(rows) => rows,
Err(_) => return Err("failed querying rows".to_string()),
};
let mut songs = Vec::new(); let mut songs = Vec::new();
for name_result in rows {
let name = match name_result { {
Ok(name) => name, let sql = media.db();
Err(_) => return Err("failed getting name from row".to_string()),
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<String>) {
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(); let mut rng = thread_rng();
songs.shuffle(&mut rng); songs.shuffle(&mut rng);
self.append_songs(ctx, msg, songs)?; append_songs(media, ctx, msg, songs)?;
Ok(()) Ok(())
} }
fn handle_song_request( fn handle_song_request(
media: &mut MediaData, media: &mut MediaData,
ctx: &mut serenity::client::Context, ctx: &serenity::client::Context,
msg: &serenity::model::channel::Message, msg: &serenity::model::channel::Message,
pattern: &str, pattern: &str,
) -> Result<(), String> { ) -> 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<String>) {
Ok(rows) => rows,
Err(_) => return Err("failed querying rows".to_string()),
};
let mut songs = Vec::new(); let mut songs = Vec::new();
for name_result in rows {
let name = match name_result { {
Ok(name) => name, let sql = media.db();
Err(_) => return Err("failed getting name from row".to_string()),
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<String>) {
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() { if !songs.is_empty() {
let mut rng = thread_rng(); let mut rng = thread_rng();
songs.shuffle(&mut rng); songs.shuffle(&mut rng);
self.append_songs(ctx, msg, songs)?; append_songs(media, ctx, msg, songs)?;
} else { } else {
print_error!(msg print_error!(msg
.channel_id .channel_id
.say(format!("no song found with pattern {}", pattern))); .say(&ctx.http, format!("no song found with pattern {}", pattern)));
} }
Ok(()) Ok(())

View file

@ -15,10 +15,10 @@ use serenity::{
#[command] #[command]
fn remove(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult { fn remove(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
let data = ctx.data.read(); let data = ctx.data.read();
let media = match data.get::<MediaData>() { let media = match data.get::<Media>() {
Ok(media) => media, Some(media) => media,
Err(_) => { None => {
msg.channel_id.say("could not find media data"); display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
return Ok(()); return Ok(());
} }
}; };
@ -34,15 +34,14 @@ fn remove(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
if !song_name.is_empty() { if !song_name.is_empty() {
match fs::remove_file(&song_name) { match fs::remove_file(&song_name) {
Ok(_) => print_error!(msg.channel_id.say(format!( Ok(_) => print_error!(msg.channel_id.say(
"Remove current song ({}) from local disk", &ctx.http,
song_name format!("Remove current song ({}) from local disk", song_name)
))), )),
Err(err) => print_error!(msg.channel_id.say(format!( Err(err) => print_error!(msg.channel_id.say(
"Error removing file ({}): {:?}", &ctx.http,
song_name, format!("Error removing file ({}): {:?}", song_name, err.kind())
err.kind() )),
))),
}; };
} }

View file

@ -19,42 +19,32 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
return Ok(()); return Ok(());
} }
if let Some(mut manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() { let mut data = ctx.data.write();
if let Some(manager_lock) = data.get_mut::<VoiceManager>().cloned() {
let mut manager = manager_lock.lock(); let mut manager = manager_lock.lock();
let guild_id = match guild_id(msg.channel_id) { let guild_id = check_result_return_ok!(guild_id(ctx, msg));
Some(id) => id,
None => {
println!("error getting guild id");
print_error!(msg.channel_id.say("error getting guild id"));
return Ok(());
}
};
if let Some(handler) = handler(guild_id, &mut manager) { if let Some(handler) = handler(guild_id, &mut manager) {
let data = ctx.data.read(); let media = match data.get_mut::<Media>() {
let mut media = match data.get_mut::<MediaData>() { Some(media) => media,
Ok(media) => media, None => {
Err(_) => { display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
msg.channel_id.say("could not find media data");
return Ok(()); 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 current song is the last song in this playlist, just return
if playlist.is_empty() { if media.playlist().is_empty() {
print_error!(msg print_error!(msg
.channel_id .channel_id
.say("playlist is empty, no next song available")); .say(&ctx.http, "playlist is empty, no next song available"));
return Ok(()); return Ok(());
} else { } else {
// remove the current song from the playlist // 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 // stop the current song from playing
handler.stop(); handler.stop();
@ -63,8 +53,8 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
let source = match ffmpeg(first.name.clone()) { let source = match ffmpeg(first.name.clone()) {
Ok(mpeg) => mpeg, Ok(mpeg) => mpeg,
Err(_) => { Err(_) => {
playlist.clear(); media.playlist_mut().clear();
*song = None; *media.song_mut() = None;
return Ok(()); return Ok(());
} }
@ -85,12 +75,13 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
None => println!("error getting callback from media"), 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(); *media.song_name_mut() = first.name.clone();
print_error!(msg print_error!(msg.channel_id.say(
.channel_id &ctx.http,
.say(format!("Skipped current song, now playing: {}", first.name))); format!("Skipped current song, now playing: {}", first.name)
));
} }
} }
} }

View file

@ -16,16 +16,16 @@ fn stop(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
return Ok(()); return Ok(());
} }
let data = ctx.data.read(); let mut data = ctx.data.write();
let mut media = match data.get_mut::<MediaData>() { let media = match data.get_mut::<Media>() {
Ok(media) => media, Some(media) => media,
Err(_) => { None => {
msg.channel_id.say("could not find media data"); display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
return Ok(()); return Ok(());
} }
}; };
print_error!(data.reset(ctx, msg)); print_error!(media.reset(ctx, msg));
Ok(()) Ok(())
} }

View file

@ -1,5 +1,6 @@
use serenity; use serenity;
use serenity::model::id::ChannelId; use serenity::model::channel::Message;
use serenity::prelude::*;
use serenity::voice::ffmpeg; use serenity::voice::ffmpeg;
use serenity::voice::LockedAudio; use serenity::voice::LockedAudio;
@ -55,21 +56,18 @@ impl MediaData {
pub fn reset( pub fn reset(
&mut self, &mut self,
ctx: &mut serenity::client::Context, ctx: &serenity::client::Context,
msg: &serenity::model::channel::Message, msg: &serenity::model::channel::Message,
) -> Result<(), String> { ) -> Result<(), String> {
self.playlist().clear(); self.playlist.clear();
self.song = None; self.current_song = None;
self.name = String::new(); self.song_name = String::new();
self.next_callback = None(); self.next_callback = None;
if let Some(manager_lock) = ctx.data.lock().get::<VoiceManager>().cloned() { if let Some(manager_lock) = ctx.data.read().get::<VoiceManager>().cloned() {
let mut manager = manager_lock.lock(); let mut manager = manager_lock.lock();
let guild_id = match guild_id(msg.channel_id) { let guild_id = guild_id(ctx, msg)?;
Some(guild_id) => guild_id,
None => return Ok(()),
};
{ {
let handler = match handler(guild_id, &mut manager) { let handler = match handler(guild_id, &mut manager) {
@ -109,60 +107,41 @@ impl MediaData {
} }
pub fn song_name(&self) -> &String { pub fn song_name(&self) -> &String {
&self.name &self.song_name
} }
pub fn song_name_mut(&mut self) -> &mut String { pub fn song_name_mut(&mut self) -> &mut String {
&mut self.name &mut self.song_name
} }
pub fn start_playing( pub fn start_playing(
mediadata: &Arc<MediaData>, ctx: &Context,
callback: Arc<Fn() -> ()>, mediadata: &mut MediaData,
channel_id: ChannelId, msg: &Message,
manager_lock: &Arc< manager_lock: &Arc<
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>, serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
>, >,
) { ) {
// check if there is already playing // check if there is already playing
let already_started = { let already_started = { mediadata.song().is_some() };
let song_lock = match mediadata.song_mut() {
Ok(song) => song,
Err(msg) => {
println!("{}", msg);
return;
}
};
let song = song_lock.borrow();
song.is_some()
};
// if there isnt already a song playing, start a new one // if there isnt already a song playing, start a new one
if !already_started { if !already_started {
*mediadata.next_callback.borrow_mut() = Some(callback.clone()); Self::next_song(ctx, mediadata, msg, manager_lock);
Self::next_song(mediadata, channel_id, manager_lock, callback);
} }
} }
pub fn next_song( pub fn next_song(
mediadata: &Arc<MediaData>, ctx: &Context,
channel_id: ChannelId, mediadata: &mut MediaData,
msg: &Message,
manager_lock: &Arc< manager_lock: &Arc<
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>, serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
>, >,
callback: Arc<Fn() -> ()>,
) { ) {
let mut manager = manager_lock.lock(); let mut manager = manager_lock.lock();
let guild_id = match guild_id(channel_id) { let guild_id = check_result_return!(guild_id(ctx, msg));
Some(id) => id,
None => {
println!("error getting guild_id");
return;
}
};
let mut need_to_leave = false; let mut need_to_leave = false;
@ -177,56 +156,31 @@ impl MediaData {
} }
}; };
let playlist_lock = match mediadata.playlist_mut() { if mediadata.playlist().is_empty() {
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() {
need_to_leave = true; need_to_leave = true;
handler.stop(); handler.stop();
*song = None; *mediadata.song_mut() = None;
*name = String::new(); *mediadata.song_name_mut() = String::new();
} else { } else {
handler.stop(); handler.stop();
let first = playlist.remove(0); let first = mediadata.playlist_mut().remove(0);
let source = match ffmpeg(first.name.clone()) { let source = match ffmpeg(first.name.clone()) {
Ok(mpeg) => mpeg, Ok(mpeg) => mpeg,
Err(_) => { Err(_) => {
playlist.clear(); mediadata.playlist_mut().clear();
return; return;
} }
}; };
*song = Some(handler.play_returning_and_callback(source, callback)); *mediadata.song_mut() = Some(handler.play_returning(source));
*name = first.name.clone(); *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 Send for MediaData {}
unsafe impl Sync for MediaData {} unsafe impl Sync for MediaData {}
pub struct Media;
impl TypeMapKey for Media {
type Value = MediaData;
}

View file

@ -1,26 +1,43 @@
use parking_lot::MutexGuard; use lock_api::{MutexGuard, RawMutex};
use serenity; 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 serenity::voice::Handler;
use std::sync::Arc;
// This imports `typemap`'s `Key` as `TypeMapKey`.
use serenity::prelude::*;
use super::prelude::*; use super::prelude::*;
pub fn guild_id(channel_id: ChannelId) -> Option<GuildId> { pub fn guild(ctx: &Context, msg: &Message) -> Result<Arc<SerRwLock<Guild>>, String> {
/* match msg.guild(&ctx.cache) {
match CACHE.read().guild_channel(channel_id) { Some(guild) => Ok(guild),
Some(channel) => Some(channel.read().guild_id),
None => { None => {
print_error!(channel_id.say("Error finding channel info")); if msg
None .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<GuildId, String> {
let guild = guild(ctx, msg)?;
let guild_read = guild.read();
Ok(guild_read.id)
}
pub fn handler<'a, T: RawMutex>(
guild_id: GuildId, 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> { ) -> Option<&'a mut Handler> {
manager.get_mut(guild_id) manager.get_mut(guild_id)
} }
@ -33,12 +50,9 @@ pub fn channel_contains_author(
match ctx.data.read().get::<VoiceManager>().cloned() { match ctx.data.read().get::<VoiceManager>().cloned() {
Some(manager_lock) => { Some(manager_lock) => {
let mut manager = manager_lock.lock(); let mut manager = manager_lock.lock();
let guild_id = match guild_id(msg.channel_id) { let guild_id = match guild_id(ctx, msg) {
Some(guild_id) => guild_id, Ok(id) => id,
None => { Err(_) => return true,
println!("error getting guild_id");
return true;
}
}; };
let handler = match handler(guild_id, &mut manager) { let handler = match handler(guild_id, &mut manager) {

View file

@ -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::ip::*;
pub use super::commands::list::*; pub use super::commands::list::*;
@ -13,4 +13,4 @@ pub use super::voicemanager::VoiceManager;
pub use super::youtube::youtube_dl; 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};

View file

@ -1,5 +1,5 @@
use parking_lot::Mutex;
use serenity::client::bridge::voice::ClientVoiceManager; use serenity::client::bridge::voice::ClientVoiceManager;
use serenity::prelude::Mutex;
use std::sync::Arc; use std::sync::Arc;
use typemap::Key; use typemap::Key;