Connect and play works again

This commit is contained in:
hodasemi 2019-09-14 16:34:00 +02:00
parent f89c8706eb
commit 53798b050d
18 changed files with 165 additions and 550 deletions

View file

@ -7,8 +7,8 @@ authors = ["hodasemi <michaelh.95@t-online.de>"]
[dependencies]
typemap = "~0.3"
serde_json = "*"
rand = "0.6"
utilities = { git = "http://dimov.cloud/hodasemi/utilities" }
rusqlite = { version = "*", features = ["bundled"] }
serenity = { version = "0.6", default-features = false, features = [ "builder", "cache", "client", "framework", "gateway", "model", "standard_framework", "utils", "voice", "rustls_backend"]}
lock_api = "0.2.0"
serenity = { version = "0.7", default-features = false, features = [ "builder", "cache", "client", "framework", "gateway", "model", "standard_framework", "utils", "voice", "rustls_backend"]}
parking_lot = "*"
failure = "*"

BIN
Penis1

Binary file not shown.

View file

@ -1,204 +0,0 @@
#![allow(dead_code)]
use std::fmt::Display;
use std::fs::File;
use std::io::{BufRead, BufReader, Write};
use std::str::FromStr;
use std::collections::HashMap;
#[derive(Clone)]
pub enum Value {
Value(String),
Array(Vec<String>),
}
struct ConfigSection {
header: String,
body: HashMap<String, Value>,
}
impl Value {
pub fn empty() -> Value {
Value::Value("".to_string())
}
pub fn value<T>(value: &T) -> Value
where
T: Display,
{
Value::Value(format!("{}", value))
}
pub fn array<T>(array: &Vec<T>) -> Value
where
T: Display,
{
Value::Array(array.iter().map(|v| format!("{}", v)).collect())
}
pub fn set_value<T>(&self, value: &mut T) -> Result<(), String>
where
T: FromStr,
{
match self {
Value::Value(value_string) => match value_string.parse::<T>() {
Ok(val) => *value = val,
Err(_) => return Err(format!("error parsing value {}", value_string)),
},
_ => return Err("key_value has wrong format".to_string()),
};
Ok(())
}
pub fn set_array<T>(&self, array: &mut Vec<T>) -> Result<(), String>
where
T: FromStr,
{
match self {
Value::Array(value_array) => {
for value_string in value_array {
match value_string.parse::<T>() {
Ok(val) => array.push(val),
Err(_) => return Err(format!("error parsing value {}", value_string)),
}
}
}
_ => return Err("key_value has wrong format".to_string()),
};
Ok(())
}
}
pub fn read_config(file_name: &str) -> Result<HashMap<String, HashMap<String, Value>>, String> {
let file = match File::open(file_name) {
Ok(file) => file,
Err(msg) => return Err(format!("error opening config file({}): {}", file_name, msg)),
};
let mut infos = HashMap::new();
let mut current_section: Option<ConfigSection> = None;
for line_res in BufReader::new(file).lines() {
if let Ok(line) = line_res {
let mut trimmed = line.trim().to_string();
if trimmed.starts_with("#") || trimmed.is_empty() {
continue;
} else if trimmed.starts_with("[") && trimmed.ends_with("]") {
trimmed.remove(0);
trimmed.pop();
if let Some(ref section) = current_section {
infos.insert(section.header.clone(), section.body.clone());
}
current_section = Some(ConfigSection {
header: trimmed,
body: HashMap::new(),
});
} else {
let mut split = trimmed.split("=");
let key = match split.nth(0) {
Some(key) => key.trim().to_string(),
None => {
println!("cannot get key from line: {}", trimmed);
continue;
}
};
let value = match split.last() {
Some(value) => value.trim().to_string(),
None => {
println!("cannot get value from line: {}", trimmed);
continue;
}
};
if value.starts_with("[") && value.ends_with("]") {
let mut trimmed_value = value;
trimmed_value.remove(0);
trimmed_value.pop();
let value_split = trimmed_value.split(";");
let value_array = value_split.map(|v| v.trim().to_string()).collect();
if let Some(ref mut section) = current_section {
section.body.insert(key, Value::Array(value_array));
}
} else {
if let Some(ref mut section) = current_section {
section.body.insert(key, Value::Value(value));
}
}
}
}
}
// also push the last section
if let Some(section) = current_section {
infos.insert(section.header, section.body);
}
Ok(infos)
}
pub fn write_config(
file_name: &str,
sections: &Vec<(String, Vec<(String, Value)>)>,
) -> Result<(), String> {
let mut file = match File::create(file_name) {
Ok(file) => file,
Err(msg) => {
return Err(format!(
"error creating config file({}): {}",
file_name, msg
))
}
};
for (header, body) in sections {
let fmt_header = format!("[{}]\n", header);
if let Err(_) = file.write_all(fmt_header.as_bytes()) {
return Err(format!("failed writing section: {}", fmt_header));
}
for (key, value) in body {
let fmt_key_value = format!(
"{} = {}\n",
key,
match value {
Value::Value(val) => val.clone(),
Value::Array(array) => {
let mut array_value = "[".to_string();
for (i, val) in array.iter().enumerate() {
// if element is not the last one
if i != array.len() - 1 {
array_value = format!("{}{}, ", array_value, val);
} else {
array_value = format!("{}{}", array_value, val);
}
}
format!("{}]", array_value)
}
}
);
if let Err(_) = file.write_all(fmt_key_value.as_bytes()) {
return Err(format!("failed writing key value: {}", fmt_key_value));
}
}
if let Err(_) = file.write_all("\n".as_bytes()) {
return Err("failed writing new line".to_string());
}
}
Ok(())
}

View file

@ -1,80 +0,0 @@
#![macro_use]
/// check result macro, where the Ok() is the type which should be returned
#[macro_export]
macro_rules! check_result {
($v:expr) => {
match $v {
Ok(t) => t,
Err(msg) => return Err(msg),
}
};
}
/// 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 {
($v:expr) => {
match $v {
Ok(t) => t,
Err(msg) => {
println!("{}", msg);
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 {
($v:expr) => {
if let Err(msg) = $v {
return Err(msg);
};
};
}
/// check result macro, where the Ok() is void, but just print the error message
#[macro_export]
macro_rules! display_error {
($v:expr) => {
if let Err(msg) = $v {
println!("{}", msg);
return;
};
};
}
/// 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 {
println!("{}", msg);
};
};
}

View file

@ -3,12 +3,9 @@
extern crate serenity;
extern crate parking_lot;
extern crate rand;
extern crate serde_json;
extern crate typemap;
mod confighandler;
mod macros;
mod player;
use serenity::{
@ -31,10 +28,11 @@ use serenity::prelude::*;
use std::sync::Arc;
use confighandler::*;
use player::prelude::*;
use std::collections::HashSet;
use utilities::prelude::*;
struct Config {
token: String,
prefix: String,
@ -55,9 +53,9 @@ group!({
commands: [ip, list, pause, play, remove, skip, stop]
});
fn main() {
fn main() -> VerboseResult<()> {
// read config file
let config_file = check_result_return!(read_config("bot.conf"));
let config_file = ConfigHandler::read_config("bot.conf")?;
let mut config = Config::default();
@ -65,26 +63,23 @@ fn main() {
Some(info) => {
match info.get("token") {
Some(token_pair) => {
display_error!(token_pair.set_value(&mut config.token));
token_pair.set_value(&mut config.token)?;
}
None => {
println!("couldn't find token inside meta section");
return;
create_error!("couldn't find token inside meta section");
}
}
match info.get("prefix") {
Some(prefix_pair) => {
display_error!(prefix_pair.set_value(&mut config.prefix));
prefix_pair.set_value(&mut config.prefix)?;
}
None => {
println!("couldn't find prefix inside meta section");
return;
create_error!("couldn't find prefix inside meta section");
}
}
}
None => {
println!("couldn't find Meta section in config file");
return;
create_error!("couldn't find Meta section in config file");
}
};
@ -95,8 +90,10 @@ fn main() {
// event handlers and framework commands.
{
let mut data = client.data.write();
data.insert::<VoiceManager>(Arc::clone(&client.voice_manager));
data.insert::<Media>(MediaData::new("Penis1").expect("failed to create media data handle"));
data.insert::<Media>(
MediaData::new("Penis1", Arc::clone(&client.voice_manager))
.expect("failed to create media data handle"),
);
}
// We will fetch your bot's owners and id
@ -161,4 +158,6 @@ fn main() {
let _ = client
.start()
.map_err(|why| println!("Client ended: {:?}", why));
Ok(())
}

View file

@ -27,8 +27,8 @@ fn ip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
}
match from_utf8(out.stdout.as_slice()) {
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(string) => msg.author.direct_message(&ctx, |m| m.content(string))?,
Err(_) => msg.channel_id.say(&ctx.http, "error getting IP string")?,
};
Ok(())

View file

@ -8,11 +8,8 @@ use serenity::{
#[command]
fn list(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
if !channel_contains_author(ctx, msg) {
println!(
"user {} is not in the same voice channel as the bot",
msg.author.name
);
if let Err(err) = channel_contains_author(ctx, msg) {
msg.channel_id.say(&ctx.http, err)?;
return Ok(());
}
@ -22,7 +19,7 @@ fn list(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
let media = match data.get::<Media>() {
Some(media) => media,
None => {
display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
msg.channel_id.say(&ctx.http, "could not find media data")?;
return Ok(());
}
};
@ -46,7 +43,7 @@ fn list(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
}
}
print_error!(msg.channel_id.say(&ctx.http, output));
msg.channel_id.say(&ctx.http, output)?;
Ok(())
}

View file

@ -10,11 +10,8 @@ use serenity::{
#[command]
fn pause(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
if !channel_contains_author(ctx, msg) {
println!(
"user {} is not in the same voice channel as the bot",
msg.author.name
);
if let Err(err) = channel_contains_author(ctx, msg) {
msg.channel_id.say(&ctx.http, err)?;
return Ok(());
}
@ -22,7 +19,7 @@ fn pause(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
let media = match data.get::<Media>() {
Some(media) => media,
None => {
display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
msg.channel_id.say(&ctx.http, "could not find media data")?;
return Ok(());
}
};

View file

@ -1,13 +1,9 @@
use lock_api::RawMutex;
use std::sync::Arc;
use rand::{seq::SliceRandom, thread_rng};
use super::super::prelude::*;
use rusqlite::params;
use rand::{seq::SliceRandom, thread_rng};
use serenity::prelude::*;
use serenity::voice::LockedAudio;
use serenity::{
@ -15,13 +11,12 @@ use serenity::{
model::channel::Message,
};
use utilities::prelude::*;
#[command]
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",
msg.author.name
);
if let Err(err) = channel_contains_author(ctx, msg) {
msg.channel_id.say(&ctx.http, err)?;
return Ok(());
}
@ -29,33 +24,32 @@ fn play(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
let media = match data.get_mut::<Media>() {
Some(media) => media,
None => {
display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
msg.channel_id.say(&ctx.http, "could not find media data")?;
return Ok(());
}
};
if args.len() == 0 {
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::<String>() {
Ok(arg) => arg,
// can't happen, since we tested for length == 1
Err(_) => return Ok(()),
};
if arg == "--local" {
handle_local_request(media, ctx, msg)?;
} else if arg.starts_with("http") {
handle_http_request(media, ctx, msg, &arg)?;
} else {
handle_song_request(media, ctx, msg, &arg)?;
msg.channel_id
.say(&ctx.http, "Must provide a URL to a video or audio")?;
}
} else {
print_error!(msg.channel_id.say(&ctx.http, "Unsupported argument list"));
let first_arg = args.current().unwrap();
if first_arg == "--local" {
handle_local_request(media, ctx, msg)?;
} else if first_arg.starts_with("http") {
handle_http_request(media, ctx, msg, first_arg)?;
} else {
let mut arg_list = String::new();
for arg in args.iter::<String>() {
arg_list += &format!(" {}", arg?.trim());
}
handle_song_request(media, ctx, msg, &arg_list)?;
}
}
Ok(())
@ -74,63 +68,15 @@ fn check_for_continue(song_lock: &Option<LockedAudio>) -> bool {
}
}
fn check_join_channel<T: RawMutex>(
manager_lock: &Arc<lock_api::Mutex<T, serenity::client::bridge::voice::ClientVoiceManager>>,
ctx: &Context,
msg: &Message,
) {
let guild = check_result_return!(guild(ctx, msg));
let guild_id = check_result_return!(guild_id(ctx, msg));
let channel_id = guild
.read()
.voice_states
.get(&msg.author.id)
.and_then(|voice_state| voice_state.channel_id);
let connect_to = match channel_id {
Some(channel) => channel,
None => {
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: &Context,
msg: &Message,
mut source: Vec<Song>,
) -> Result<(), String> {
) -> VerboseResult<()> {
media.playlist_mut().append(&mut source);
if let Some(manager_lock) = ctx.data.read().get::<VoiceManager>().cloned() {
check_join_channel(&manager_lock, ctx, msg);
// let check_finished = {
// let channel_id = msg.channel_id;
// let manager_lock_clone = manager_lock.clone();
// 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::start_playing(ctx, media, msg, &manager_lock);
}
MediaData::start_playing(ctx, media, msg)?;
Ok(())
}
@ -139,8 +85,8 @@ fn handle_http_request(
media: &mut MediaData,
ctx: &serenity::client::Context,
msg: &serenity::model::channel::Message,
url: &String,
) -> Result<(), String> {
url: &str,
) -> VerboseResult<()> {
let mut names = Vec::new();
{
@ -148,18 +94,18 @@ fn handle_http_request(
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()),
Err(_) => create_error!("failed preparing data base access"),
};
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()),
Err(_) => create_error!("failed querying rows"),
};
for name_result in rows {
let name = match name_result {
Ok(name) => name,
Err(_) => return Err("failed getting name from row".to_string()),
Err(_) => create_error!("failed getting name from row"),
};
names.push(name);
@ -167,7 +113,9 @@ fn handle_http_request(
}
if names.len() > 0 {
print_error!(msg.channel_id.say(&ctx.http, "song already loaded!"));
msg.channel_id
.say(&ctx.http, "song already loaded!")
.map_err(|err| format!("{}", err))?;
append_songs(
media,
@ -181,9 +129,9 @@ fn handle_http_request(
Err(why) => {
println!("Err starting source: {:?}", why);
print_error!(msg
.channel_id
.say(&ctx.http, format!("Error using youtube-dl: {}", why)));
msg.channel_id
.say(&ctx.http, format!("Error using youtube-dl: {}", why))
.map_err(|err| format!("{}", err))?;
return Ok(());
}
@ -209,12 +157,14 @@ fn handle_http_request(
)
.is_err()
{
return Err("failed inserting songs into db".to_string());
create_error!("failed inserting songs into db");
}
}
}
print_error!(msg.channel_id.say(&ctx.http, info));
msg.channel_id
.say(&ctx.http, info)
.map_err(|err| format!("{}", err))?;
append_songs(media, ctx, msg, source)?;
}
@ -226,7 +176,7 @@ fn handle_local_request(
media: &mut MediaData,
ctx: &serenity::client::Context,
msg: &serenity::model::channel::Message,
) -> Result<(), String> {
) -> VerboseResult<()> {
let mut songs = Vec::new();
{
@ -234,18 +184,18 @@ fn handle_local_request(
let mut stmt = match sql.prepare("SELECT name FROM Vulva3") {
Ok(statement) => statement,
Err(_) => return Err("failed preparing data base access".to_string()),
Err(_) => create_error!("failed preparing data base access"),
};
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()),
Err(_) => create_error!("failed querying rows"),
};
for name_result in rows {
let name = match name_result {
Ok(name) => name,
Err(_) => return Err("failed getting name from row".to_string()),
Err(_) => create_error!("failed getting name from row"),
};
songs.push(Song { name });
@ -265,7 +215,7 @@ fn handle_song_request(
ctx: &serenity::client::Context,
msg: &serenity::model::channel::Message,
pattern: &str,
) -> Result<(), String> {
) -> VerboseResult<()> {
let mut songs = Vec::new();
{
@ -276,18 +226,18 @@ fn handle_song_request(
pattern
)) {
Ok(statement) => statement,
Err(_) => return Err("failed preparing data base access".to_string()),
Err(_) => create_error!("failed preparing data base access"),
};
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()),
Err(_) => create_error!("failed querying rows"),
};
for name_result in rows {
let name = match name_result {
Ok(name) => name,
Err(_) => return Err("failed getting name from row".to_string()),
Err(_) => create_error!("failed getting name from row"),
};
songs.push(Song { name });
@ -300,9 +250,9 @@ fn handle_song_request(
append_songs(media, ctx, msg, songs)?;
} else {
print_error!(msg
.channel_id
.say(&ctx.http, format!("no song found with pattern {}", pattern)));
msg.channel_id
.say(&ctx.http, format!("no song found with pattern {}", pattern))
.map_err(|err| format!("{}", err))?;
}
Ok(())

View file

@ -18,7 +18,7 @@ fn remove(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
let media = match data.get::<Media>() {
Some(media) => media,
None => {
display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
msg.channel_id.say(&ctx.http, "could not find media data")?;
return Ok(());
}
};
@ -34,14 +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(
Ok(_) => msg.channel_id.say(
&ctx.http,
format!("Remove current song ({}) from local disk", song_name)
)),
Err(err) => print_error!(msg.channel_id.say(
format!("Remove current song ({}) from local disk", song_name),
)?,
Err(err) => msg.channel_id.say(
&ctx.http,
format!("Error removing file ({}): {:?}", song_name, err.kind())
)),
format!("Error removing file ({}): {:?}", song_name, err.kind()),
)?,
};
}

View file

@ -11,35 +11,24 @@ use serenity::{
#[command]
fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
if !channel_contains_author(ctx, msg) {
println!(
"user {} is not in the same voice channel as the bot",
msg.author.name
);
if let Err(err) = channel_contains_author(ctx, msg) {
msg.channel_id.say(&ctx.http, err)?;
return Ok(());
}
let mut data = ctx.data.write();
if let Some(manager_lock) = data.get_mut::<VoiceManager>().cloned() {
let mut manager = manager_lock.lock();
if let Some(media) = data.get_mut::<Media>() {
let voice_manager = media.voice_manager.clone();
let mut manager = voice_manager.lock();
let guild_id = check_result_return_ok!(guild_id(ctx, msg));
let guild_id = guild_id(ctx, msg)?;
if let Some(handler) = handler(guild_id, &mut manager) {
let media = match data.get_mut::<Media>() {
Some(media) => media,
None => {
display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
return Ok(());
}
};
// if current song is the last song in this playlist, just return
if media.playlist().is_empty() {
print_error!(msg
.channel_id
.say(&ctx.http, "playlist is empty, no next song available"));
msg.channel_id
.say(&ctx.http, "playlist is empty, no next song available")?;
return Ok(());
} else {
@ -78,10 +67,10 @@ fn skip(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
*media.song_mut() = Some(handler.play_returning(source));
*media.song_name_mut() = first.name.clone();
print_error!(msg.channel_id.say(
msg.channel_id.say(
&ctx.http,
format!("Skipped current song, now playing: {}", first.name)
));
format!("Skipped current song, now playing: {}", first.name),
)?;
}
}
}

View file

@ -8,11 +8,8 @@ use serenity::{
#[command]
fn stop(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
if !channel_contains_author(ctx, msg) {
println!(
"user {} is not in the same voice channel as the bot",
msg.author.name
);
if let Err(err) = channel_contains_author(ctx, msg) {
msg.channel_id.say(&ctx.http, err)?;
return Ok(());
}
@ -20,12 +17,12 @@ fn stop(ctx: &mut Context, msg: &Message, _: Args) -> CommandResult {
let media = match data.get_mut::<Media>() {
Some(media) => media,
None => {
display_error_ok!(msg.channel_id.say(&ctx.http, "could not find media data"));
msg.channel_id.say(&ctx.http, "could not find media data")?;
return Ok(());
}
};
print_error!(media.reset(ctx, msg));
media.reset(ctx, msg)?;
Ok(())
}

View file

@ -4,12 +4,16 @@ 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,
}
@ -18,13 +22,18 @@ pub struct MediaData {
playlist: Vec<Song>,
current_song: Option<LockedAudio>,
song_name: String,
pub next_callback: Option<Arc<Fn() -> ()>>,
pub next_callback: Option<Arc<dyn Fn() -> ()>>,
sql_data_base: Connection,
pub voice_manager: Arc<Mutex<ClientVoiceManager>>,
}
impl MediaData {
pub fn new(file: &str) -> Result<MediaData, String> {
pub fn new(
file: &str,
voice_manager: Arc<Mutex<ClientVoiceManager>>,
) -> Result<MediaData, String> {
let connection = match Connection::open(file) {
Ok(file) => file,
Err(_) => return Err(format!("can't open {}", file)),
@ -51,6 +60,8 @@ impl MediaData {
next_callback: None,
sql_data_base: connection,
voice_manager,
})
}
@ -64,8 +75,8 @@ impl MediaData {
self.song_name = String::new();
self.next_callback = None;
if let Some(manager_lock) = ctx.data.read().get::<VoiceManager>().cloned() {
let mut manager = manager_lock.lock();
if let Some(media) = ctx.data.read().get::<Media>() {
let mut manager = media.voice_manager.lock();
let guild_id = guild_id(ctx, msg)?;
@ -118,30 +129,23 @@ impl MediaData {
ctx: &Context,
mediadata: &mut MediaData,
msg: &Message,
manager_lock: &Arc<
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
>,
) {
) -> VerboseResult<()> {
// check if there is already playing
let already_started = { mediadata.song().is_some() };
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, manager_lock);
Self::next_song(ctx, mediadata, msg)?;
}
Ok(())
}
pub fn next_song(
ctx: &Context,
mediadata: &mut MediaData,
msg: &Message,
manager_lock: &Arc<
serenity::prelude::Mutex<serenity::client::bridge::voice::ClientVoiceManager>,
>,
) {
let mut manager = manager_lock.lock();
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 = check_result_return!(guild_id(ctx, msg));
let guild_id = guild_id(ctx, msg)?;
let mut need_to_leave = false;
@ -150,8 +154,7 @@ impl MediaData {
match handler(guild_id, &mut manager) {
Some(handler) => handler,
None => {
println!("error getting handler");
return;
create_error!("error getting handler");
}
}
};
@ -171,22 +174,24 @@ impl MediaData {
Err(_) => {
mediadata.playlist_mut().clear();
return;
return Ok(());
}
};
*mediadata.song_mut() = Some(handler.play_returning(source));
*mediadata.song_name_mut() = first.name.clone();
print_error!(msg
.channel_id
.say(&ctx.http, format!("Playing song: {}", first.name)));
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(())
}
}

View file

@ -1,7 +1,6 @@
pub mod eventhandler;
pub mod mediadata;
pub mod player;
pub mod voicemanager;
mod youtube;
pub mod commands;

View file

@ -1,4 +1,4 @@
use lock_api::{MutexGuard, RawMutex};
use parking_lot::lock_api::{MutexGuard, RawMutex};
use serenity;
use serenity::model::channel::Message;
use serenity::model::guild::Guild;
@ -8,6 +8,8 @@ use serenity::voice::Handler;
use std::sync::Arc;
use utilities::prelude::*;
// This imports `typemap`'s `Key` as `TypeMapKey`.
use serenity::prelude::*;
@ -45,64 +47,39 @@ pub fn handler<'a, T: RawMutex>(
pub fn channel_contains_author(
ctx: &mut serenity::client::Context,
msg: &serenity::model::channel::Message,
) -> bool {
let (guild_id, voice_channel_id_bot) = {
match ctx.data.read().get::<VoiceManager>().cloned() {
Some(manager_lock) => {
let mut manager = manager_lock.lock();
let guild_id = match guild_id(ctx, msg) {
Ok(id) => id,
Err(_) => return true,
};
) -> VerboseResult<()> {
let guild = guild(ctx, msg)?;
let guild_id = guild.read().id;
let handler = match handler(guild_id, &mut manager) {
Some(handler) => handler,
None => {
println!("error getting handler");
return true;
let author_channel_id = match guild
.read()
.voice_states
.get(&msg.author.id)
.and_then(|voice_state| voice_state.channel_id)
{
Some(channel) => channel,
None => create_error!("author is not in a voice channel!"),
};
if let Some(media) = ctx.data.read().get::<Media>() {
let mut manager = media.voice_manager.lock();
match manager.get(guild_id) {
Some(handler) => match handler.channel_id {
Some(bot_channel_id) => {
if bot_channel_id != author_channel_id {
create_error!("author is not in the same voice channel as the bot!");
}
};
(
guild_id,
match handler.channel_id {
Some(id) => id,
None => {
println!("error getting channel_id for bot");
return true;
}
},
)
}
None => {
manager.join(guild_id, author_channel_id);
}
},
None => {
manager.join(guild_id, author_channel_id);
}
None => return false,
}
};
let author = &msg.author;
let guild = match guild_id.to_guild_cached(&ctx) {
Some(guild) => guild,
None => {
println!("error getting guild from cache");
return true;
}
};
let guild_lock = guild.read();
let voice_state = match guild_lock.voice_states.get(&author.id) {
Some(state) => state,
None => {
println!("error getting voice state from user {}", author.name);
return false;
}
};
if let Some(voice_channel_id_user) = voice_state.channel_id {
if voice_channel_id_bot != voice_channel_id_user {
return false;
}
}
true
Ok(())
}

View file

@ -9,7 +9,6 @@ pub use super::commands::skip::*;
pub use super::commands::stop::*;
pub use super::eventhandler::Handler;
pub use super::voicemanager::VoiceManager;
pub use super::youtube::youtube_dl;

View file

@ -1,10 +0,0 @@
use serenity::client::bridge::voice::ClientVoiceManager;
use serenity::prelude::Mutex;
use std::sync::Arc;
use typemap::Key;
pub struct VoiceManager;
impl Key for VoiceManager {
type Value = Arc<Mutex<ClientVoiceManager>>;
}

View file

@ -72,7 +72,7 @@ pub fn youtube_dl(uri: &str) -> Result<Vec<Song>, String> {
));
}
let files = check_result!(convert_output(&out));
let files = convert_output(&out)?;
for file in &files {
println!("file: {}", file);