2019-07-12 12:41:51 +00:00
|
|
|
use lock_api::RawMutex;
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
use std::sync::Arc;
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2018-11-14 15:43:53 +00:00
|
|
|
use rand::{seq::SliceRandom, thread_rng};
|
|
|
|
|
2018-11-14 14:29:58 +00:00
|
|
|
use super::super::prelude::*;
|
|
|
|
|
2019-04-03 09:42:06 +00:00
|
|
|
use rusqlite::params;
|
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
use serenity::prelude::*;
|
|
|
|
use serenity::voice::LockedAudio;
|
|
|
|
use serenity::{
|
|
|
|
framework::standard::{macros::command, Args, CommandResult},
|
|
|
|
model::channel::Message,
|
|
|
|
};
|
|
|
|
|
|
|
|
#[command]
|
2019-07-12 12:41:51 +00:00
|
|
|
fn play(ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
|
2019-07-12 08:39:03 +00:00
|
|
|
if !channel_contains_author(ctx, msg) {
|
|
|
|
println!(
|
|
|
|
"user {} is not in the same voice channel as the bot",
|
|
|
|
msg.author.name
|
|
|
|
);
|
|
|
|
return Ok(());
|
2018-11-14 14:29:58 +00:00
|
|
|
}
|
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
let mut data = ctx.data.write();
|
|
|
|
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"));
|
2019-07-12 08:39:03 +00:00
|
|
|
return Ok(());
|
2018-11-14 14:29:58 +00:00
|
|
|
}
|
2019-07-12 08:39:03 +00:00
|
|
|
};
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
if args.len() == 0 {
|
2019-07-12 12:41:51 +00:00
|
|
|
if !check_for_continue(media.song_mut()) {
|
|
|
|
print_error!(msg
|
|
|
|
.channel_id
|
|
|
|
.say(&ctx.http, "Must provide a URL to a video or audio"));
|
2019-07-12 08:39:03 +00:00
|
|
|
}
|
|
|
|
} 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(()),
|
2018-11-14 14:29:58 +00:00
|
|
|
};
|
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
if arg == "--local" {
|
2019-07-12 12:41:51 +00:00
|
|
|
handle_local_request(media, ctx, msg)?;
|
2019-07-12 08:39:03 +00:00
|
|
|
} else if arg.starts_with("http") {
|
2019-07-12 12:41:51 +00:00
|
|
|
handle_http_request(media, ctx, msg, &arg)?;
|
2019-07-12 08:39:03 +00:00
|
|
|
} else {
|
2019-07-12 12:41:51 +00:00
|
|
|
handle_song_request(media, ctx, msg, &arg)?;
|
2018-11-14 15:43:53 +00:00
|
|
|
}
|
2019-07-12 08:39:03 +00:00
|
|
|
} else {
|
2019-07-12 12:41:51 +00:00
|
|
|
print_error!(msg.channel_id.say(&ctx.http, "Unsupported argument list"));
|
2019-07-12 08:39:03 +00:00
|
|
|
}
|
2018-11-14 15:43:53 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2019-04-28 12:13:36 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
fn check_for_continue(song_lock: &Option<LockedAudio>) -> bool {
|
|
|
|
match song_lock {
|
2019-07-12 08:39:03 +00:00
|
|
|
Some(song) => {
|
|
|
|
let song_clone = song.clone();
|
|
|
|
let mut audio_lock = song_clone.lock();
|
2019-04-28 12:13:36 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
audio_lock.play();
|
|
|
|
true
|
|
|
|
}
|
|
|
|
None => false,
|
|
|
|
}
|
|
|
|
}
|
2019-04-28 12:13:36 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
fn check_join_channel<T: RawMutex>(
|
|
|
|
manager_lock: &Arc<lock_api::Mutex<T, serenity::client::bridge::voice::ClientVoiceManager>>,
|
|
|
|
ctx: &Context,
|
|
|
|
msg: &Message,
|
2019-07-12 08:39:03 +00:00
|
|
|
) {
|
2019-07-12 12:41:51 +00:00
|
|
|
let guild = check_result_return!(guild(ctx, msg));
|
|
|
|
let guild_id = check_result_return!(guild_id(ctx, msg));
|
2018-11-14 15:43:53 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
let channel_id = guild
|
|
|
|
.read()
|
|
|
|
.voice_states
|
|
|
|
.get(&msg.author.id)
|
|
|
|
.and_then(|voice_state| voice_state.channel_id);
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
let connect_to = match channel_id {
|
|
|
|
Some(channel) => channel,
|
|
|
|
None => {
|
2019-07-12 12:41:51 +00:00
|
|
|
display_error!(msg.reply(ctx, "Not in a voice channel"));
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
return;
|
2019-04-03 09:42:06 +00:00
|
|
|
}
|
2019-07-12 08:39:03 +00:00
|
|
|
};
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
let mut manager = manager_lock.lock();
|
|
|
|
manager.join(guild_id, connect_to);
|
|
|
|
}
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
fn append_songs(
|
|
|
|
media: &mut MediaData,
|
2019-07-12 12:41:51 +00:00
|
|
|
ctx: &Context,
|
|
|
|
msg: &Message,
|
2019-07-12 08:39:03 +00:00
|
|
|
mut source: Vec<Song>,
|
|
|
|
) -> Result<(), String> {
|
2019-07-12 12:41:51 +00:00
|
|
|
media.playlist_mut().append(&mut source);
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
if let Some(manager_lock) = ctx.data.read().get::<VoiceManager>().cloned() {
|
|
|
|
check_join_channel(&manager_lock, ctx, msg);
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
// 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);
|
2019-07-12 08:39:03 +00:00
|
|
|
}
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
fn handle_http_request(
|
|
|
|
media: &mut MediaData,
|
2019-07-12 12:41:51 +00:00
|
|
|
ctx: &serenity::client::Context,
|
2019-07-12 08:39:03 +00:00
|
|
|
msg: &serenity::model::channel::Message,
|
|
|
|
url: &String,
|
|
|
|
) -> Result<(), String> {
|
2019-07-12 12:41:51 +00:00
|
|
|
let mut names = Vec::new();
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
{
|
|
|
|
let sql = media.db();
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
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()),
|
|
|
|
};
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
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()),
|
2018-11-14 14:42:56 +00:00
|
|
|
};
|
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
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);
|
|
|
|
}
|
2019-07-12 08:39:03 +00:00
|
|
|
}
|
2018-11-14 14:42:56 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
if names.len() > 0 {
|
2019-07-12 12:41:51 +00:00
|
|
|
print_error!(msg.channel_id.say(&ctx.http, "song already loaded!"));
|
2018-11-14 14:42:56 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
append_songs(
|
|
|
|
media,
|
2019-07-12 08:39:03 +00:00
|
|
|
ctx,
|
|
|
|
msg,
|
|
|
|
names.iter().map(|n| Song { name: n.clone() }).collect(),
|
|
|
|
)?;
|
2019-07-12 12:41:51 +00:00
|
|
|
} else {
|
|
|
|
let source = match youtube_dl(&url) {
|
|
|
|
Ok(source) => source,
|
|
|
|
Err(why) => {
|
|
|
|
println!("Err starting source: {:?}", why);
|
2019-04-28 12:13:36 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
print_error!(msg
|
|
|
|
.channel_id
|
|
|
|
.say(&ctx.http, format!("Error using youtube-dl: {}", why)));
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
};
|
2018-11-14 15:43:53 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
let mut info = if source.len() == 1 {
|
|
|
|
"Finished downloading song:".to_string()
|
|
|
|
} else {
|
|
|
|
"Finished downloading songs:".to_string()
|
|
|
|
};
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
{
|
|
|
|
let sql = media.db();
|
2018-11-14 15:43:53 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
for song in &source {
|
|
|
|
info = format!("{}\n\t{}", info, song.name);
|
2019-04-28 12:13:36 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
if sql
|
|
|
|
.execute(
|
|
|
|
"INSERT INTO Vulva3 (name, link)
|
2019-07-12 08:39:03 +00:00
|
|
|
VALUES (?1, ?2)",
|
2019-07-12 12:41:51 +00:00
|
|
|
params![song.name, url],
|
|
|
|
)
|
|
|
|
.is_err()
|
|
|
|
{
|
|
|
|
return Err("failed inserting songs into db".to_string());
|
|
|
|
}
|
|
|
|
}
|
2018-11-14 15:43:53 +00:00
|
|
|
}
|
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
print_error!(msg.channel_id.say(&ctx.http, info));
|
2018-11-14 15:43:53 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
append_songs(media, ctx, msg, source)?;
|
|
|
|
}
|
2019-04-28 12:13:36 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
fn handle_local_request(
|
|
|
|
media: &mut MediaData,
|
2019-07-12 12:41:51 +00:00
|
|
|
ctx: &serenity::client::Context,
|
2019-07-12 08:39:03 +00:00
|
|
|
msg: &serenity::model::channel::Message,
|
|
|
|
) -> Result<(), String> {
|
2019-07-12 12:41:51 +00:00
|
|
|
let mut songs = Vec::new();
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
{
|
|
|
|
let sql = media.db();
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
let mut stmt = match sql.prepare("SELECT name FROM Vulva3") {
|
|
|
|
Ok(statement) => statement,
|
|
|
|
Err(_) => return Err("failed preparing data base access".to_string()),
|
|
|
|
};
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
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()),
|
2019-04-28 12:13:36 +00:00
|
|
|
};
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
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 });
|
|
|
|
}
|
2019-07-12 08:39:03 +00:00
|
|
|
}
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
let mut rng = thread_rng();
|
|
|
|
songs.shuffle(&mut rng);
|
2019-04-28 12:13:36 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
append_songs(media, ctx, msg, songs)?;
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2019-04-03 09:42:06 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
fn handle_song_request(
|
|
|
|
media: &mut MediaData,
|
2019-07-12 12:41:51 +00:00
|
|
|
ctx: &serenity::client::Context,
|
2019-07-12 08:39:03 +00:00
|
|
|
msg: &serenity::model::channel::Message,
|
|
|
|
pattern: &str,
|
|
|
|
) -> Result<(), String> {
|
2019-07-12 12:41:51 +00:00
|
|
|
let mut songs = Vec::new();
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
{
|
|
|
|
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()),
|
|
|
|
};
|
2019-07-12 08:39:03 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
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()),
|
2019-07-12 08:39:03 +00:00
|
|
|
};
|
2019-04-28 12:13:36 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
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 });
|
|
|
|
}
|
2019-04-03 09:42:06 +00:00
|
|
|
}
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2019-07-12 08:39:03 +00:00
|
|
|
if !songs.is_empty() {
|
|
|
|
let mut rng = thread_rng();
|
|
|
|
songs.shuffle(&mut rng);
|
2018-11-14 14:29:58 +00:00
|
|
|
|
2019-07-12 12:41:51 +00:00
|
|
|
append_songs(media, ctx, msg, songs)?;
|
2019-07-12 08:39:03 +00:00
|
|
|
} else {
|
|
|
|
print_error!(msg
|
|
|
|
.channel_id
|
2019-07-12 12:41:51 +00:00
|
|
|
.say(&ctx.http, format!("no song found with pattern {}", pattern)));
|
2018-11-14 14:29:58 +00:00
|
|
|
}
|
2019-07-12 08:39:03 +00:00
|
|
|
|
|
|
|
Ok(())
|
2018-11-14 14:29:58 +00:00
|
|
|
}
|