194 lines
5.3 KiB
Rust
194 lines
5.3 KiB
Rust
use parking_lot;
|
|
|
|
use serenity;
|
|
use serenity::voice::LockedAudio;
|
|
|
|
use std::cell::RefCell;
|
|
use std::fs;
|
|
use std::ops::DerefMut;
|
|
use std::sync::{Arc, MutexGuard};
|
|
|
|
use rand::{seq::SliceRandom, thread_rng};
|
|
|
|
use super::super::prelude::*;
|
|
|
|
pub struct Play {
|
|
media: Arc<MediaData>,
|
|
}
|
|
|
|
impl Play {
|
|
pub fn new(media_data: Arc<MediaData>) -> Play {
|
|
Play { media: media_data }
|
|
}
|
|
|
|
fn check_for_continue(song_lock: MutexGuard<RefCell<Option<LockedAudio>>>) -> bool {
|
|
match song_lock.borrow_mut().deref_mut() {
|
|
Some(song) => {
|
|
let song_clone = song.clone();
|
|
let mut audio_lock = song_clone.lock();
|
|
|
|
audio_lock.play();
|
|
true
|
|
}
|
|
None => false,
|
|
}
|
|
}
|
|
|
|
fn check_join_channel(
|
|
manager_lock: &Arc<parking_lot::Mutex<serenity::client::bridge::voice::ClientVoiceManager>>,
|
|
msg: &serenity::model::channel::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 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("Not in a voice channel"));
|
|
|
|
return;
|
|
}
|
|
};
|
|
|
|
let mut manager = manager_lock.lock();
|
|
|
|
manager.join(guild_id, connect_to);
|
|
}
|
|
|
|
fn append_songs(
|
|
&self,
|
|
ctx: &mut serenity::client::Context,
|
|
msg: &serenity::model::channel::Message,
|
|
mut source: Vec<Song>,
|
|
) {
|
|
{
|
|
let playlist_mutex = self.media.playlist_mut();
|
|
playlist_mutex.borrow_mut().append(&mut source);
|
|
}
|
|
|
|
let manager_lock = ctx.data.lock().get::<VoiceManager>().cloned().unwrap();
|
|
|
|
Self::check_join_channel(&manager_lock, msg);
|
|
|
|
MediaData::start_thread(&self.media, msg.channel_id, &manager_lock);
|
|
}
|
|
|
|
fn handle_http_request(
|
|
&self,
|
|
ctx: &mut serenity::client::Context,
|
|
msg: &serenity::model::channel::Message,
|
|
url: &String,
|
|
) {
|
|
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;
|
|
}
|
|
};
|
|
|
|
let mut info = if source.len() == 1 {
|
|
"Finished downloading song:".to_string()
|
|
} else {
|
|
"Finished downloading songs:".to_string()
|
|
};
|
|
|
|
for song in &source {
|
|
info = format!("{}\n\t{}", info, song.name);
|
|
}
|
|
|
|
print_error!(msg.channel_id.say(info));
|
|
|
|
self.append_songs(ctx, msg, source);
|
|
}
|
|
|
|
fn handle_local_request(
|
|
&self,
|
|
ctx: &mut serenity::client::Context,
|
|
msg: &serenity::model::channel::Message,
|
|
) {
|
|
print_error!(self.media.reset(ctx, msg));
|
|
|
|
let files = fs::read_dir("./").unwrap();
|
|
|
|
let mut songs = Vec::new();
|
|
|
|
for file in files {
|
|
let os_name = file.unwrap().file_name();
|
|
let name = os_name.to_str().unwrap();
|
|
|
|
if name != "RMusicBot" && name != "bot.conf" && name != "start.sh" {
|
|
songs.push(Song {
|
|
name: name.to_string(),
|
|
});
|
|
}
|
|
}
|
|
|
|
let mut rng = thread_rng();
|
|
songs.shuffle(&mut rng);
|
|
|
|
self.append_songs(ctx, msg, songs);
|
|
}
|
|
}
|
|
|
|
impl serenity::framework::standard::Command for Play {
|
|
#[allow(unreachable_code, unused_mut)]
|
|
fn execute(
|
|
&self,
|
|
mut ctx: &mut serenity::client::Context,
|
|
msg: &serenity::model::channel::Message,
|
|
mut args: serenity::framework::standard::Args,
|
|
) -> ::std::result::Result<(), serenity::framework::standard::CommandError> {
|
|
if !channel_contains_author(ctx, msg) {
|
|
println!(
|
|
"user {} is not in the same voice channel as the bot",
|
|
msg.author.name
|
|
);
|
|
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"));
|
|
}
|
|
} 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" {
|
|
self.handle_local_request(ctx, msg);
|
|
} else if arg.starts_with("http") {
|
|
self.handle_http_request(ctx, msg, &arg);
|
|
} else {
|
|
print_error!(msg.channel_id.say("Unsupported argument list"));
|
|
}
|
|
} else {
|
|
print_error!(msg.channel_id.say("Unsupported argument list"));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|