feat: added skip command, reworked embed messages

fix: fixed issue with queue not working properly
This commit is contained in:
moonleay 2024-03-10 19:36:02 +01:00
parent 1dcd0ab66b
commit ba0f1fb959
Signed by: moonleay
GPG key ID: 82667543CCD715FB
10 changed files with 159 additions and 114 deletions

View file

@ -1,6 +1,7 @@
use crate::music::{music_manager, music_queue};
use serenity::all::{ChannelId, GuildId, Http};
use serenity::async_trait;
use songbird::input::Compose;
use songbird::{Event, EventContext, EventHandler};
use std::sync::Arc;
@ -21,7 +22,7 @@ impl EventHandler for TrackEndNotifier {
let q = &music_queue.queue;
if q.is_empty() {
// No more songs in queue, exit the vc
let stopped = match music_manager::stop(&self.cmdctx, &self.guild_id).await {
let stopped = match music_manager::leave(&self.cmdctx, &self.guild_id).await {
Ok(stopped) => stopped,
Err(e) => {
println!("Cannot stop: {:?}", e);
@ -29,6 +30,7 @@ impl EventHandler for TrackEndNotifier {
}
};
if stopped {
music_queue::delete_queue(&self.guild_id).await;
println!("Stopped playing successfully.");
} else {
println!("Failed to stop playing.");
@ -40,7 +42,8 @@ impl EventHandler for TrackEndNotifier {
println!("Cannot get head of queue");
return None;
}
let head = head.unwrap();
let mut head = head.unwrap();
println!("Now playing: {}", head.aux_metadata().await.unwrap().title.unwrap());
music_manager::play_song(&self.cmdctx, &self.guild_id, &head).await;
}

View file

@ -5,11 +5,12 @@ use crate::util::user_util::get_vc_id;
use crate::HttpKey;
use serenity::all::{Context, CreateEmbed, GuildId, UserId};
use songbird::error::JoinError;
use songbird::input::{Compose, YoutubeDl};
use songbird::input::YoutubeDl;
use songbird::{Event, TrackEvent};
use std::sync::Arc;
use std::time::Duration;
/// Either queues the song, or start playing it instantly, depending on if there is already a song playing
pub async fn attempt_to_queue_song(
ctx: &Context,
guild_id: &GuildId,
@ -18,21 +19,17 @@ pub async fn attempt_to_queue_song(
query: &str,
) -> CreateEmbed {
if !user_util::is_user_connected_to_vc(ctx, guild_id, user_id).await {
return Embed::create(
username,
"You are not connected to a VC",
"Connect to my VC to control the music.",
);
return Embed::create_error_respose(username, "You are not connected to a VC", "Connect to my vc to start controlling the music.")
}
let connect_to = match get_vc_id(ctx, guild_id, user_id).await {
Some(channel_id) => channel_id,
None => {
return Embed::create(username, "Error", "Cannot get channel id");
return Embed::create_error_respose(username, "Error", "Cannot find channel_id.");
}
};
let manager = &songbird::get(ctx) // TODO match
let manager: &Arc<songbird::Songbird> = &songbird::get(ctx) // TODO match
.await
.expect("Cannot get Songbird.")
.clone();
@ -42,23 +39,18 @@ pub async fn attempt_to_queue_song(
// self is connected to vc, check if user is in same vc
if self_channel.is_none() {
// TODO This could maybe be removed?
// Connect to VC
manager
manager // TODO match
.join(*guild_id, connect_to)
.await
.expect("Cannot connect>...");
}
} else {
let self_channel = self_channel.expect("Cannot get self channel");
let self_channel = self_channel.expect("Cannot get self channel");// TODO: match
// Check if user is in the same VC as the bot
if self_channel != connect_to {
return Embed::create(
username,
"You are not in my VC.",
"Connect to my VC to control the music.",
);
return Embed::create_error_respose(username, "You are not in my VC", "You have to be in my VC in order to controll the music.")
}
}
@ -72,7 +64,7 @@ pub async fn attempt_to_queue_song(
};
// Create source
let mut src = if do_search {
let src = if do_search {
YoutubeDl::new_search(http_client, query.to_string())
} else {
YoutubeDl::new(http_client, query.to_string())
@ -82,11 +74,7 @@ pub async fn attempt_to_queue_song(
music_queue::add_to_queue(guild_id, src.clone()).await;
if currently_playing.is_some() {
// Add to queue
return Embed::create(
username,
"Added to queue",
"The song was added to the queue.",
);
return Embed::create_yt_playing(src, username, "Added to queue").await;
}
let _query = music_queue::get_head(guild_id)
@ -97,7 +85,7 @@ pub async fn attempt_to_queue_song(
let handler_lock = match manager.get(*guild_id) {
Some(handler) => handler,
None => {
return Embed::create("", "Error", "Cannot get handler");
return Embed::create_error_respose(username, "Error", "Cannot get handler of this guild.");
}
};
@ -114,33 +102,10 @@ pub async fn attempt_to_queue_song(
},
);
// Get metadata
let metadata = src.aux_metadata().await.expect("Cannot get metadata");
let title = metadata.title.unwrap_or("Unknown title".to_string());
let author = metadata.artist.unwrap_or("Unknown artist".to_string());
let duration = metadata.duration.unwrap_or(Duration::from_millis(0));
let thumbnail = metadata
.thumbnail
.unwrap_or("https://http.cat/images/404.jpg".to_string());
let link = metadata
.source_url
.unwrap_or("https://piped.moonleay.net/404".to_string());
Embed::create(
username,
"Added to queue",
format!(
"{} by {} ({}min {}sec) was added to the queue.\n [[Link]({})]",
title,
author,
duration.as_secs() / 60,
duration.as_secs() % 60,
link
),
)
.thumbnail(thumbnail)
Embed::create_yt_playing(src, username, "Now playing").await
}
/// Play the provided song
pub async fn play_song(ctx: &Context, guild_id: &GuildId, target: &YoutubeDl) {
let manager = &songbird::get(ctx) // TODO match
.await
@ -159,9 +124,60 @@ pub async fn play_song(ctx: &Context, guild_id: &GuildId, target: &YoutubeDl) {
};
let mut handler = handler_lock.lock().await;
let _ = handler.stop(); // Stop playing the current song
let _ = handler.play_input(target.clone().into()); // TODO: Add event handlers
}
/// Attempt to skip the song, which is currently playing. Do nothing if there is no next song
pub async fn attempt_to_skip_current_song(ctx: &Context, guild_id: &GuildId, user_id: &UserId, username: &str) -> CreateEmbed {
if !user_util::is_user_connected_to_vc(ctx, guild_id, user_id).await {
return Embed::create_error_respose(username, "You are not connected to a VC", "Connect to my vc to start controlling the music.")
}
let connect_to = match get_vc_id(ctx, guild_id, user_id).await {
Some(channel_id) => channel_id,
None => {
return Embed::create_error_respose(username, "Error", "Cannot find channel_id.");
}
};
let manager: &Arc<songbird::Songbird> = &songbird::get(ctx) // TODO match
.await
.expect("Cannot get Songbird.")
.clone();
let self_channel = user_util::get_self_vc_id(ctx, guild_id).await;
if !user_util::is_self_connected_to_vc(ctx, guild_id).await {
// self is connected to vc, check if user is in same vc
if self_channel.is_none() {
// Connect to VC
manager // TODO match
.join(*guild_id, connect_to)
.await
.expect("Cannot connect>...");
}
} else {
let self_channel = self_channel.expect("Cannot get self channel");// TODO: match
// Check if user is in the same VC as the bot
if self_channel != connect_to {
return Embed::create_error_respose(username, "You are not in my VC", "You have to be in my VC in order to controll the music.")
}
}
let head = music_queue::get_head(guild_id).await; // TODO match
if head.is_none() {
return Embed::create_error_respose(username, "Cannot find a song to play", "The queue is empty.");
}
let head = head.unwrap();
play_song(ctx, guild_id, &head).await;
Embed::create_yt_playing(head, username, "Song skipped; Now playing").await
}
/// Try to clear the queue and stop playing. Also leave the vc
pub async fn attempt_to_stop(
ctx: &Context,
guild_id: &GuildId,
@ -170,11 +186,7 @@ pub async fn attempt_to_stop(
) -> CreateEmbed {
if !user_util::is_self_connected_to_vc(ctx, guild_id).await {
// Bot is not connectd to vc; no need to dc
return Embed::create(
username,
"Bot is not connected",
"And therefore there is no need to do anything.",
);
return Embed::create_error_respose(username, "Bot is not connected", "And therefore there is no need to do anything.");
}
let self_channel = user_util::get_self_vc_id(ctx, guild_id)
.await
@ -185,48 +197,38 @@ pub async fn attempt_to_stop(
// Check if user is in the same VC as the bot
if self_channel != connect_to {
return Embed::create(
username,
"You are not in my VC.",
"Connect to my VC to control the music.",
);
return Embed::create_error_respose(username, "You are not in my VC.", "Connect to my VC to controll the music.");
}
let stopped = match stop(ctx, guild_id).await {
let stopped = match leave(ctx, guild_id).await {
Ok(stopped) => stopped,
Err(e) => {
println!("Error while stopping: {:?}", e);
return Embed::create(
username,
"There was an error",
"Tell moonleay to check the logs.".to_string(),
);
return Embed::create_error_respose(username, "There was an error", "Tell moonleay to check the logs.");
}
};
if !stopped {
Embed::create(
username,
"Can't stop, what ain't running.",
"I am not connected. I cant stop doing something, when I'm not doing it".to_string(),
)
Embed::create_error_respose(username, "Can't stop, what ain't running", "I am not connected.\nI cant stop doing something, when I'm not doing it.")
} else {
music_queue::delete_queue(guild_id).await; // Clear queue
Embed::create(username, "I stopped and left", "Just like your girlfriend.")
Embed::create_success_response(username, "I stopped and left", "Just like you girlfriend.")
}
}
// Make the bot leave the voice channel. Returns Ok(true) if bot was connected, returns Ok(false) if bot was not connected. Returns Err if something went wrong.
pub async fn stop(ctx: &Context, guild_id: &GuildId) -> Result<bool, JoinError> {
/// Make the bot leave the voice channel. Returns Ok(true) if bot was connected, returns Ok(false) if bot was not connected. Returns Err if something went wrong.
pub async fn leave(ctx: &Context, guild_id: &GuildId) -> Result<bool, JoinError> {
let manager = songbird::get(ctx)
.await
.expect("Cannot get Songbird")
.clone();
let has_handler = manager.get(*guild_id).is_some();
let handler = manager.get(*guild_id);
let has_handler = handler.is_some();
if has_handler {
handler.unwrap().lock().await.stop();
manager.remove(*guild_id).await?;
return Ok(true); // Handler removed
}