135 lines
4.8 KiB
Rust
135 lines
4.8 KiB
Rust
use log::{debug, warn, error};
|
|
|
|
use serenity::{prelude::*, async_trait};
|
|
use serenity::builder::CreateApplicationCommand;
|
|
use serenity::model::application::interaction::application_command::ApplicationCommandInteraction;
|
|
use songbird::EventHandler;
|
|
|
|
use crate::bot::commands::audio::{join, leave, add_song, get_songbird, AudioConfigs};
|
|
|
|
use super::{create_response, edit_response};
|
|
|
|
pub async fn run(ctx: &Context, command: &ApplicationCommandInteraction) {
|
|
// Get the track url
|
|
let track_url = match command.data.options.get(0) {
|
|
Some(t) => match &t.value {
|
|
Some(v) => match v.as_str() {
|
|
Some(s) => s.to_owned(),
|
|
None => {
|
|
warn!("Missing track option");
|
|
if let Err(why) = create_response(&ctx, &command, format!("Track option is missing")).await {
|
|
error!("Failed to create response message: {}", why);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
None => {
|
|
warn!("Missing track option");
|
|
if let Err(why) = create_response(&ctx, &command, format!("Track option is missing")).await {
|
|
error!("Failed to create response message: {}", why);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
None => {
|
|
warn!("Missing track option");
|
|
if let Err(why) = create_response(&ctx, &command, format!("Track option is missing")).await {
|
|
error!("Failed to create response message: {}", why);
|
|
}
|
|
return;
|
|
}
|
|
};
|
|
|
|
// Create the initial response
|
|
if let Err(why) = create_response(&ctx, &command, format!("Processing command...")).await {
|
|
error!("Failed to create response message: {}", why);
|
|
return;
|
|
}
|
|
|
|
match join(&ctx, &command.guild_id, &command.user).await {
|
|
Ok(_) => {
|
|
let guild_id = match command.guild_id {
|
|
Some(g) => g,
|
|
None => {
|
|
if let Err(why) = edit_response(&ctx, &command, "Unable to join voice channel".to_string()).await {
|
|
error!("Failed to edit response message: {}", why);
|
|
}
|
|
return;
|
|
}
|
|
};
|
|
debug!("Play command executed with track: {:?}", track_url);
|
|
|
|
let manager = get_songbird(ctx).await;
|
|
if let Some(handler_lock) = manager.get(guild_id) {
|
|
let is_queue_empty = {
|
|
let call_handler = handler_lock.lock().await;
|
|
call_handler.queue().is_empty()
|
|
};
|
|
let audio_config = {
|
|
let data_read = ctx.data.read().await;
|
|
data_read.get::<AudioConfigs>().expect("Expected AudioConfigs in TypeMap.").clone()
|
|
};
|
|
let ac = audio_config.read().await;
|
|
match add_song(handler_lock.clone(), &track_url, is_queue_empty, ac.get(&guild_id)).await {
|
|
Ok(added_song) => {
|
|
let track_title = added_song.title.unwrap();
|
|
debug!("Added track: {}", track_title);
|
|
if let Err(why) = edit_response(&ctx, &command, format!("Added track to queue: {}", track_title)).await {
|
|
error!("Failed to edit response message: {}", why);
|
|
}
|
|
let mut handler = handler_lock.lock().await;
|
|
handler.remove_all_global_events();
|
|
handler.add_global_event(songbird::Event::Track(songbird::TrackEvent::End), TrackEndNotifier { guild_id, call: manager })
|
|
}
|
|
Err(why) => {
|
|
warn!("Failed to add song: {}", why);
|
|
if let Err(why) = edit_response(&ctx, &command, format!("Failed to add song: {}", why)).await {
|
|
error!("Failed to edit response message: {}", why);
|
|
}
|
|
if let Err(why) = leave(&ctx, &command.guild_id).await {
|
|
error!("Failed to leave voice channel: {}", why);
|
|
}
|
|
return;
|
|
}
|
|
};
|
|
}
|
|
},
|
|
Err(err) => {
|
|
warn!("{}", err);
|
|
if let Err(why) = edit_response(&ctx, &command, format!("{}", err)).await {
|
|
error!("Failed to edit response message: {}", why);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn register(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand {
|
|
command.name("play").description("Plays the given track").create_option(|option| { option
|
|
.name("track")
|
|
.description("The track to be played")
|
|
.kind(serenity::model::prelude::command::CommandOptionType::String)
|
|
.required(true)
|
|
})
|
|
}
|
|
|
|
struct TrackEndNotifier {
|
|
pub call: std::sync::Arc<songbird::Songbird>,
|
|
pub guild_id: serenity::model::id::GuildId
|
|
}
|
|
|
|
#[async_trait]
|
|
impl EventHandler for TrackEndNotifier {
|
|
async fn act(&self, ctx: &songbird::events::EventContext<'_>) -> Option<songbird::events::Event> {
|
|
if let songbird::EventContext::Track(_track_list) = ctx {
|
|
if let Some(call) = self.call.get(self.guild_id) {
|
|
let mut handler = call.lock().await;
|
|
if handler.queue().is_empty() {
|
|
debug!("Queue is empty, leaving voice channel");
|
|
handler.leave().await.unwrap();
|
|
}
|
|
}
|
|
}
|
|
None
|
|
}
|
|
}
|