Simplified enqueue_track to parse track type (playlist or single track)
This commit is contained in:
@@ -9,7 +9,7 @@ use songbird::{Event, EventHandler, Songbird, TrackEvent};
|
||||
|
||||
use crate::bot::commands::audio::leave_voice_channel;
|
||||
use crate::data::guilds::GuildCache;
|
||||
use crate::bot::ytdlp::{PlaylistItem, YtDlp};
|
||||
use crate::bot::ytdlp::{YtDlp, YtDlpItem};
|
||||
use crate::error::{SirenResult, Error as SirenError};
|
||||
use crate::HttpKey;
|
||||
|
||||
@@ -57,12 +57,12 @@ pub async fn run(ctx: &Context, command: &CommandInteraction) {
|
||||
log::debug!("<{guild_id}> Play command executed on {channel_id} with track: {track_url:?}");
|
||||
// Handle the track url
|
||||
match enqueue_track(ctx, manager, guild_id.to_owned(), track_url).await {
|
||||
Ok(count) => {
|
||||
let mut message = format!("Playing {} tracks", count);
|
||||
if count == 0 {
|
||||
Ok(items) => {
|
||||
let mut message = format!("Added {} tracks", items.len());
|
||||
if items.len() == 0 {
|
||||
message = "No tracks were played".to_string();
|
||||
} else if count == 1 {
|
||||
message = "Playing 1 track".to_string();
|
||||
} else if items.len() == 1 {
|
||||
message = format!("Added **{}**", items[0].get_title());
|
||||
}
|
||||
edit_response(&ctx, &command, message).await;
|
||||
}
|
||||
@@ -84,42 +84,32 @@ pub async fn enqueue_track(
|
||||
manager: Arc<Songbird>,
|
||||
guild_id: GuildId,
|
||||
track_url: &str,
|
||||
) -> SirenResult<i32> {
|
||||
let mut track_count = 0;
|
||||
) -> SirenResult<Vec<YtDlpItem>> {
|
||||
let mut playlist_items: Vec<YtDlpItem> = Vec::new();
|
||||
if let Some(handler_lock) = manager.get(guild_id) {
|
||||
let mut handler = handler_lock.lock().await;
|
||||
let guild = GuildCache::get_by_id(guild_id.get() as i64).await?.unwrap();
|
||||
let valid = is_valid_url(&track_url);
|
||||
|
||||
// Check if the URL is valid
|
||||
if !valid.0 {
|
||||
if !valid {
|
||||
log::warn!("<{guild_id}> Invalid track url: {}", track_url);
|
||||
return Err(SirenError::new(
|
||||
422,
|
||||
format!("Invalid track url: {}", track_url),
|
||||
));
|
||||
}
|
||||
let mut playlist_items: Vec<PlaylistItem> = Vec::new();
|
||||
// Check if the URL is a playlist or a single track
|
||||
if valid.1 {
|
||||
playlist_items = match get_playlist_urls(&track_url) {
|
||||
Ok(items) => items,
|
||||
Err(err) => {
|
||||
log::warn!("<{guild_id}> Failed to get playlist urls: {}", err);
|
||||
return Err(SirenError::new(422, err.to_string()));
|
||||
}
|
||||
};
|
||||
} else {
|
||||
let playlist_item = PlaylistItem {
|
||||
id: "".to_string(),
|
||||
url: track_url.to_string(),
|
||||
title: "".to_string(),
|
||||
duration: 0,
|
||||
playlist_index: 0,
|
||||
};
|
||||
playlist_items.push(playlist_item);
|
||||
}
|
||||
|
||||
playlist_items = match get_ytdlp_items(&track_url) {
|
||||
Ok(items) => items,
|
||||
Err(err) => {
|
||||
log::warn!("<{guild_id}> Failed to get playlist urls: {}", err);
|
||||
return Err(SirenError::new(422, err.to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
// Add each track to the queue
|
||||
for item in playlist_items {
|
||||
for item in &playlist_items {
|
||||
let volume = guild.volume as f32 / 100.0;
|
||||
let http_client = {
|
||||
let data = ctx.data.read().await;
|
||||
@@ -128,21 +118,17 @@ pub async fn enqueue_track(
|
||||
.cloned()
|
||||
.expect("Guaranteed to exist in the typemap.")
|
||||
};
|
||||
let source = YoutubeDl::new(http_client, item.url.to_owned());
|
||||
let mut input: Input = source.into();
|
||||
let metadata = match input.aux_metadata().await {
|
||||
Ok(metadata) => metadata,
|
||||
Err(err) => {
|
||||
log::warn!("<{guild_id}> Failed to get metadata for track: {err}");
|
||||
let _ = leave_voice_channel(&manager, &guild_id).await;
|
||||
return Err(SirenError::new(422, err.to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
let source = YoutubeDl::new(http_client, item.get_url().to_owned());
|
||||
let input: Input = source.into();
|
||||
let track_title = item.get_title().to_owned();
|
||||
|
||||
let track_handle: TrackHandle;
|
||||
track_handle = handler.enqueue_input(input).await;
|
||||
|
||||
// Set the volume
|
||||
let _ = track_handle.set_volume(volume);
|
||||
let track_title = metadata.title.unwrap();
|
||||
|
||||
log::debug!("<{guild_id}> Added track: {}", track_title);
|
||||
handler.remove_all_global_events();
|
||||
handler.add_global_event(
|
||||
@@ -152,29 +138,28 @@ pub async fn enqueue_track(
|
||||
call: manager.clone(),
|
||||
},
|
||||
);
|
||||
track_count += 1;
|
||||
}
|
||||
if handler.queue().is_empty() {
|
||||
let _ = handler.queue().resume();
|
||||
}
|
||||
}
|
||||
Ok(track_count)
|
||||
Ok(playlist_items)
|
||||
}
|
||||
|
||||
pub fn get_playlist_urls(url: &str) -> SirenResult<Vec<PlaylistItem>> {
|
||||
pub fn get_ytdlp_items(url: &str) -> SirenResult<Vec<YtDlpItem>> {
|
||||
let output = YtDlp::new()
|
||||
.arg("--flat-playlist")
|
||||
.arg("--dump-json")
|
||||
.arg(url)
|
||||
.execute()?;
|
||||
let items: Vec<PlaylistItem> = String::from_utf8(output.stdout)?
|
||||
let items: Vec<YtDlpItem> = String::from_utf8(output.stdout)?
|
||||
.split('\n')
|
||||
.filter_map(|line| {
|
||||
if line.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
serde_json::from_slice::<PlaylistItem>(line.as_bytes())
|
||||
serde_json::from_slice::<YtDlpItem>(line.as_bytes())
|
||||
.map_err(|err| SirenError::new(500, err.to_string())),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user