feat: added skip command, reworked embed messages
fix: fixed issue with queue not working properly
This commit is contained in:
parent
1dcd0ab66b
commit
ba0f1fb959
10 changed files with 159 additions and 114 deletions
|
@ -6,11 +6,7 @@ use crate::util::embed::Embed;
|
||||||
pub async fn run(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
pub async fn run(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||||
let username = command.user.name.as_str();
|
let username = command.user.name.as_str();
|
||||||
|
|
||||||
Embed::create(
|
Embed::create_success_response(username, "Botendo v7", "developed by [moonleay](https://moonleay.net)\n\nCheck out the repository: https://git.moonleay.net/DiscordBots/Rustendo")
|
||||||
"",
|
|
||||||
"Botendo v7",
|
|
||||||
"developed by [moonleay](https://moonleay.net)\n\nCheck out the repository: https://git.moonleay.net/DiscordBots/Rustendo",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register() -> CreateCommand {
|
pub fn register() -> CreateCommand {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod info;
|
pub mod info;
|
||||||
pub mod play;
|
pub mod play;
|
||||||
pub mod stop;
|
pub mod stop;
|
||||||
|
pub mod skip;
|
|
@ -19,13 +19,13 @@ pub async unsafe fn run(ctx: &Context, command: &CommandInteraction) -> CreateEm
|
||||||
});
|
});
|
||||||
|
|
||||||
if query.is_none() {
|
if query.is_none() {
|
||||||
return Embed::create(username, "Error 400", "There is no query provided");
|
return Embed::create_error_respose(username, "400: Bad request", "There is no query provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
let guild_id = match &command.guild_id {
|
let guild_id = match &command.guild_id {
|
||||||
Some(guild_id) => guild_id,
|
Some(guild_id) => guild_id,
|
||||||
None => {
|
None => {
|
||||||
return Embed::create(username, "GuildId not found", "Could not find guild id.");
|
return Embed::create_error_respose(username, "guild_id not found", "Could not find guild id.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
24
src/commands/skip.rs
Normal file
24
src/commands/skip.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use crate::music::music_manager;
|
||||||
|
use crate::util::embed::Embed;
|
||||||
|
use serenity::all::{CommandInteraction, Context};
|
||||||
|
use serenity::builder::{CreateCommand, CreateEmbed};
|
||||||
|
|
||||||
|
pub async unsafe fn run(ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||||
|
let username = command.user.name.as_str();
|
||||||
|
|
||||||
|
let guild_id = match &command.guild_id {
|
||||||
|
Some(guild_id) => guild_id,
|
||||||
|
None => {
|
||||||
|
return Embed::create_error_respose(username, "guild_id not found", "Could not find guild id.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
music_manager::attempt_to_skip_current_song(ctx, guild_id, &command.user.id, &command.user.name).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register() -> CreateCommand {
|
||||||
|
CreateCommand::new("skip").description("Skip to the next song in queue")
|
||||||
|
}
|
||||||
|
|
||||||
|
// >18/02/2024 @ 19:01:59 - bartlo
|
||||||
|
// >2024-02-19 17:58:39 | moonleay
|
|
@ -9,7 +9,7 @@ pub async unsafe fn run(ctx: &Context, command: &CommandInteraction) -> CreateEm
|
||||||
let guild_id = match &command.guild_id {
|
let guild_id = match &command.guild_id {
|
||||||
Some(guild_id) => guild_id,
|
Some(guild_id) => guild_id,
|
||||||
None => {
|
None => {
|
||||||
return Embed::create(username, "GuildId not found", "Could not find guild id.");
|
return Embed::create_error_respose(username, "guild_id not found", "Could not find guild id.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,7 @@ impl EventHandler for Handler {
|
||||||
"info" => commands::info::run(&ctx, &command).await,
|
"info" => commands::info::run(&ctx, &command).await,
|
||||||
"play" => commands::play::run(&ctx, &command).await,
|
"play" => commands::play::run(&ctx, &command).await,
|
||||||
"stop" => commands::stop::run(&ctx, &command).await,
|
"stop" => commands::stop::run(&ctx, &command).await,
|
||||||
|
"skip" => commands::skip::run(&ctx, &command).await,
|
||||||
_ => respond_with_error(&ctx, &command).await,
|
_ => respond_with_error(&ctx, &command).await,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -90,6 +91,7 @@ impl EventHandler for Handler {
|
||||||
let _command = Command::create_global_command(&ctx.http, commands::info::register()).await;
|
let _command = Command::create_global_command(&ctx.http, commands::info::register()).await;
|
||||||
let _command = Command::create_global_command(&ctx.http, commands::stop::register()).await;
|
let _command = Command::create_global_command(&ctx.http, commands::stop::register()).await;
|
||||||
let _command = Command::create_global_command(&ctx.http, commands::play::register()).await;
|
let _command = Command::create_global_command(&ctx.http, commands::play::register()).await;
|
||||||
|
let _command = Command::create_global_command(&ctx.http, commands::skip::register()).await;
|
||||||
println!("Commands are registered and Rustendo is ready for Freddy.");
|
println!("Commands are registered and Rustendo is ready for Freddy.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,11 +122,7 @@ impl EventHandler for Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn respond_with_error(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
pub async fn respond_with_error(_ctx: &Context, command: &CommandInteraction) -> CreateEmbed {
|
||||||
Embed::create(
|
Embed::create_error_respose(command.user.name.as_str(), "Command not found", "Cannot find the executed command")
|
||||||
command.user.name.to_owned(),
|
|
||||||
"Command not found",
|
|
||||||
"Cannot find the executed command",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::music::{music_manager, music_queue};
|
use crate::music::{music_manager, music_queue};
|
||||||
use serenity::all::{ChannelId, GuildId, Http};
|
use serenity::all::{ChannelId, GuildId, Http};
|
||||||
use serenity::async_trait;
|
use serenity::async_trait;
|
||||||
|
use songbird::input::Compose;
|
||||||
use songbird::{Event, EventContext, EventHandler};
|
use songbird::{Event, EventContext, EventHandler};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
@ -21,7 +22,7 @@ impl EventHandler for TrackEndNotifier {
|
||||||
let q = &music_queue.queue;
|
let q = &music_queue.queue;
|
||||||
if q.is_empty() {
|
if q.is_empty() {
|
||||||
// No more songs in queue, exit the vc
|
// 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,
|
Ok(stopped) => stopped,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Cannot stop: {:?}", e);
|
println!("Cannot stop: {:?}", e);
|
||||||
|
@ -29,6 +30,7 @@ impl EventHandler for TrackEndNotifier {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if stopped {
|
if stopped {
|
||||||
|
music_queue::delete_queue(&self.guild_id).await;
|
||||||
println!("Stopped playing successfully.");
|
println!("Stopped playing successfully.");
|
||||||
} else {
|
} else {
|
||||||
println!("Failed to stop playing.");
|
println!("Failed to stop playing.");
|
||||||
|
@ -40,7 +42,8 @@ impl EventHandler for TrackEndNotifier {
|
||||||
println!("Cannot get head of queue");
|
println!("Cannot get head of queue");
|
||||||
return None;
|
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;
|
music_manager::play_song(&self.cmdctx, &self.guild_id, &head).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,12 @@ use crate::util::user_util::get_vc_id;
|
||||||
use crate::HttpKey;
|
use crate::HttpKey;
|
||||||
use serenity::all::{Context, CreateEmbed, GuildId, UserId};
|
use serenity::all::{Context, CreateEmbed, GuildId, UserId};
|
||||||
use songbird::error::JoinError;
|
use songbird::error::JoinError;
|
||||||
use songbird::input::{Compose, YoutubeDl};
|
use songbird::input::YoutubeDl;
|
||||||
use songbird::{Event, TrackEvent};
|
use songbird::{Event, TrackEvent};
|
||||||
use std::sync::Arc;
|
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(
|
pub async fn attempt_to_queue_song(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
guild_id: &GuildId,
|
guild_id: &GuildId,
|
||||||
|
@ -18,21 +19,17 @@ pub async fn attempt_to_queue_song(
|
||||||
query: &str,
|
query: &str,
|
||||||
) -> CreateEmbed {
|
) -> CreateEmbed {
|
||||||
if !user_util::is_user_connected_to_vc(ctx, guild_id, user_id).await {
|
if !user_util::is_user_connected_to_vc(ctx, guild_id, user_id).await {
|
||||||
return Embed::create(
|
return Embed::create_error_respose(username, "You are not connected to a VC", "Connect to my vc to start controlling the music.")
|
||||||
username,
|
|
||||||
"You are not connected to a VC",
|
|
||||||
"Connect to my VC to control the music.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let connect_to = match get_vc_id(ctx, guild_id, user_id).await {
|
let connect_to = match get_vc_id(ctx, guild_id, user_id).await {
|
||||||
Some(channel_id) => channel_id,
|
Some(channel_id) => channel_id,
|
||||||
None => {
|
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
|
.await
|
||||||
.expect("Cannot get Songbird.")
|
.expect("Cannot get Songbird.")
|
||||||
.clone();
|
.clone();
|
||||||
|
@ -42,23 +39,18 @@ pub async fn attempt_to_queue_song(
|
||||||
// self is connected to vc, check if user is in same vc
|
// self is connected to vc, check if user is in same vc
|
||||||
|
|
||||||
if self_channel.is_none() {
|
if self_channel.is_none() {
|
||||||
// TODO This could maybe be removed?
|
|
||||||
// Connect to VC
|
// Connect to VC
|
||||||
manager
|
manager // TODO match
|
||||||
.join(*guild_id, connect_to)
|
.join(*guild_id, connect_to)
|
||||||
.await
|
.await
|
||||||
.expect("Cannot connect>...");
|
.expect("Cannot connect>...");
|
||||||
}
|
}
|
||||||
} else {
|
} 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
|
// Check if user is in the same VC as the bot
|
||||||
if self_channel != connect_to {
|
if self_channel != connect_to {
|
||||||
return Embed::create(
|
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.")
|
||||||
username,
|
|
||||||
"You are not in my VC.",
|
|
||||||
"Connect to my VC to control the music.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +64,7 @@ pub async fn attempt_to_queue_song(
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create source
|
// Create source
|
||||||
let mut src = if do_search {
|
let src = if do_search {
|
||||||
YoutubeDl::new_search(http_client, query.to_string())
|
YoutubeDl::new_search(http_client, query.to_string())
|
||||||
} else {
|
} else {
|
||||||
YoutubeDl::new(http_client, query.to_string())
|
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;
|
music_queue::add_to_queue(guild_id, src.clone()).await;
|
||||||
if currently_playing.is_some() {
|
if currently_playing.is_some() {
|
||||||
// Add to queue
|
// Add to queue
|
||||||
return Embed::create(
|
return Embed::create_yt_playing(src, username, "Added to queue").await;
|
||||||
username,
|
|
||||||
"Added to queue",
|
|
||||||
"The song was added to the queue.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let _query = music_queue::get_head(guild_id)
|
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) {
|
let handler_lock = match manager.get(*guild_id) {
|
||||||
Some(handler) => handler,
|
Some(handler) => handler,
|
||||||
None => {
|
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
|
Embed::create_yt_playing(src, username, "Now playing").await
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Play the provided song
|
||||||
pub async fn play_song(ctx: &Context, guild_id: &GuildId, target: &YoutubeDl) {
|
pub async fn play_song(ctx: &Context, guild_id: &GuildId, target: &YoutubeDl) {
|
||||||
let manager = &songbird::get(ctx) // TODO match
|
let manager = &songbird::get(ctx) // TODO match
|
||||||
.await
|
.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 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
|
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(
|
pub async fn attempt_to_stop(
|
||||||
ctx: &Context,
|
ctx: &Context,
|
||||||
guild_id: &GuildId,
|
guild_id: &GuildId,
|
||||||
|
@ -170,11 +186,7 @@ pub async fn attempt_to_stop(
|
||||||
) -> CreateEmbed {
|
) -> CreateEmbed {
|
||||||
if !user_util::is_self_connected_to_vc(ctx, guild_id).await {
|
if !user_util::is_self_connected_to_vc(ctx, guild_id).await {
|
||||||
// Bot is not connectd to vc; no need to dc
|
// Bot is not connectd to vc; no need to dc
|
||||||
return Embed::create(
|
return Embed::create_error_respose(username, "Bot is not connected", "And therefore there is no need to do anything.");
|
||||||
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)
|
let self_channel = user_util::get_self_vc_id(ctx, guild_id)
|
||||||
.await
|
.await
|
||||||
|
@ -185,48 +197,38 @@ pub async fn attempt_to_stop(
|
||||||
|
|
||||||
// Check if user is in the same VC as the bot
|
// Check if user is in the same VC as the bot
|
||||||
if self_channel != connect_to {
|
if self_channel != connect_to {
|
||||||
return Embed::create(
|
return Embed::create_error_respose(username, "You are not in my VC.", "Connect to my VC to controll the music.");
|
||||||
username,
|
|
||||||
"You are not in my VC.",
|
|
||||||
"Connect to my VC to control the music.",
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let stopped = match stop(ctx, guild_id).await {
|
let stopped = match leave(ctx, guild_id).await {
|
||||||
Ok(stopped) => stopped,
|
Ok(stopped) => stopped,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error while stopping: {:?}", e);
|
println!("Error while stopping: {:?}", e);
|
||||||
return Embed::create(
|
return Embed::create_error_respose(username, "There was an error", "Tell moonleay to check the logs.");
|
||||||
username,
|
|
||||||
"There was an error",
|
|
||||||
"Tell moonleay to check the logs.".to_string(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !stopped {
|
if !stopped {
|
||||||
Embed::create(
|
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.")
|
||||||
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(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
music_queue::delete_queue(guild_id).await; // Clear queue
|
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.
|
/// 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> {
|
pub async fn leave(ctx: &Context, guild_id: &GuildId) -> Result<bool, JoinError> {
|
||||||
let manager = songbird::get(ctx)
|
let manager = songbird::get(ctx)
|
||||||
.await
|
.await
|
||||||
.expect("Cannot get Songbird")
|
.expect("Cannot get Songbird")
|
||||||
.clone();
|
.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 {
|
if has_handler {
|
||||||
|
handler.unwrap().lock().await.stop();
|
||||||
manager.remove(*guild_id).await?;
|
manager.remove(*guild_id).await?;
|
||||||
return Ok(true); // Handler removed
|
return Ok(true); // Handler removed
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,6 @@ use std::error::Error;
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub discord_token: String,
|
pub discord_token: String,
|
||||||
pub lavalink_address: String,
|
|
||||||
pub lavalink_password: String,
|
|
||||||
pub user_id: u64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CONFIG_FILE: &str = "./data/config.json";
|
const CONFIG_FILE: &str = "./data/config.json";
|
||||||
|
@ -26,9 +23,6 @@ pub fn load() -> Result<Config, Box<dyn Error>> {
|
||||||
fn create_empty() -> fs::File {
|
fn create_empty() -> fs::File {
|
||||||
let example_config = Config {
|
let example_config = Config {
|
||||||
discord_token: "paste_your_token".to_string(),
|
discord_token: "paste_your_token".to_string(),
|
||||||
lavalink_address: "paste_your_lavalink_address".to_string(),
|
|
||||||
lavalink_password: "paste_your_lavalink_password".to_string(),
|
|
||||||
user_id: 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut config_file = fs::File::create(CONFIG_FILE).unwrap();
|
let mut config_file = fs::File::create(CONFIG_FILE).unwrap();
|
||||||
|
|
|
@ -1,29 +1,56 @@
|
||||||
use std::fmt::Display;
|
use std::time::Duration;
|
||||||
|
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use serenity::all::{CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
use serenity::all::{Color, CreateEmbed, CreateEmbedAuthor, CreateEmbedFooter};
|
||||||
|
use songbird::input::{Compose, YoutubeDl};
|
||||||
|
|
||||||
pub struct Embed;
|
pub struct Embed;
|
||||||
|
|
||||||
impl Embed {
|
impl Embed {
|
||||||
pub fn create<
|
pub fn create_success_response(username: &str, title: &str, desc: &str) -> CreateEmbed {
|
||||||
S: Into<String> + Display,
|
|
||||||
T: Into<String> + Display,
|
|
||||||
U: Into<String> + Display,
|
|
||||||
>(
|
|
||||||
username: S,
|
|
||||||
title: T,
|
|
||||||
message: U,
|
|
||||||
) -> CreateEmbed {
|
|
||||||
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||||
|
|
||||||
CreateEmbed::new()
|
CreateEmbed::new()
|
||||||
.author(CreateEmbedAuthor::new(username.to_string()))
|
.title(title)
|
||||||
.title(title)
|
.description(desc)
|
||||||
.description(message)
|
.color(Color::from_rgb(224, 49, 26))
|
||||||
.footer(CreateEmbedFooter::new(format!(
|
.footer(CreateEmbedFooter::new(format!("> {} - {}", current_time, username)))
|
||||||
"> {} - {}",
|
}
|
||||||
current_time, username
|
|
||||||
)))
|
pub fn create_error_respose(username: &str, error_title: &str, error_desc: &str) -> CreateEmbed {
|
||||||
|
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||||
|
|
||||||
|
CreateEmbed::new()
|
||||||
|
.author(CreateEmbedAuthor::new("Oops, something went wrong."))
|
||||||
|
.title(error_title)
|
||||||
|
.description(error_desc)
|
||||||
|
.color(Color::from_rgb(224, 49, 26))
|
||||||
|
.footer(CreateEmbedFooter::new(format!("> {} - {}", current_time, username)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_yt_playing(mut src: YoutubeDl, username: &str, show_as_author: &str) -> CreateEmbed {
|
||||||
|
let current_time = Local::now().format("%Y-%m-%d @ %H:%M:%S");
|
||||||
|
|
||||||
|
// Get metadata
|
||||||
|
let metadata = src.aux_metadata().await.expect("Cannot get metadata");
|
||||||
|
let title = metadata.title.unwrap_or("Unknown title".to_string());
|
||||||
|
let artist = 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/403.jpg".to_string());
|
||||||
|
let link = metadata
|
||||||
|
.source_url
|
||||||
|
.unwrap_or("https://piped.moonleay.net/403".to_string());
|
||||||
|
|
||||||
|
CreateEmbed::new()
|
||||||
|
.author(CreateEmbedAuthor::new(show_as_author))
|
||||||
|
.title(title)
|
||||||
|
.url(link)
|
||||||
|
.thumbnail(thumbnail)
|
||||||
|
.field("Artist", artist, true)
|
||||||
|
.field("Duration", format!("{}min {}sec", duration.as_secs() / 58, duration.as_secs() % 59), true)
|
||||||
|
.color(Color::from_rgb(81, 224, 26))
|
||||||
|
.footer(CreateEmbedFooter::new(format!("> {} - {}",current_time, username)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue