queue play command

This commit is contained in:
jude 2022-02-13 16:12:42 +00:00
parent 821f283969
commit febeeefb01
6 changed files with 187 additions and 5 deletions

View File

@ -5,7 +5,7 @@ authors = ["jellywx <judesouthworth@pm.me>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
songbird = { git = "https://github.com/serenity-rs/songbird", branch = "next" } songbird = { git = "https://github.com/serenity-rs/songbird", branch = "next", features = ["builtin-queue"] }
poise = { git = "https://github.com/kangalioo/poise", branch = "master", features = ["collector"] } poise = { git = "https://github.com/kangalioo/poise", branch = "master", features = ["collector"] }
sqlx = { version = "0.5", default-features = false, features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal"] } sqlx = { version = "0.5", default-features = false, features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal"] }
dotenv = "0.15" dotenv = "0.15"

View File

@ -2,6 +2,8 @@ use poise::serenity::{
builder::CreateActionRow, model::interactions::message_component::ButtonStyle, builder::CreateActionRow, model::interactions::message_component::ButtonStyle,
}; };
use crate::models::guild_data::CtxGuildData;
use crate::utils::{join_channel, queue_audio};
use crate::{ use crate::{
cmds::autocomplete_sound, models::sound::SoundCtx, utils::play_from_query, Context, Error, cmds::autocomplete_sound, models::sound::SoundCtx, utils::play_from_query, Context, Error,
}; };
@ -32,6 +34,167 @@ pub async fn play(
Ok(()) Ok(())
} }
/// Play up to 25 sounds on queue
#[poise::command(slash_command, rename = "queue")]
pub async fn queue_play(
ctx: Context<'_>,
#[description = "Name or ID for queue position 1"]
#[autocomplete = "autocomplete_sound"]
sound_1: String,
#[description = "Name or ID for queue position 2"]
#[autocomplete = "autocomplete_sound"]
sound_2: String,
#[description = "Name or ID for queue position 3"]
#[autocomplete = "autocomplete_sound"]
sound_3: Option<String>,
#[description = "Name or ID for queue position 4"]
#[autocomplete = "autocomplete_sound"]
sound_4: Option<String>,
#[description = "Name or ID for queue position 5"]
#[autocomplete = "autocomplete_sound"]
sound_5: Option<String>,
#[description = "Name or ID for queue position 6"]
#[autocomplete = "autocomplete_sound"]
sound_6: Option<String>,
#[description = "Name or ID for queue position 7"]
#[autocomplete = "autocomplete_sound"]
sound_7: Option<String>,
#[description = "Name or ID for queue position 8"]
#[autocomplete = "autocomplete_sound"]
sound_8: Option<String>,
#[description = "Name or ID for queue position 9"]
#[autocomplete = "autocomplete_sound"]
sound_9: Option<String>,
#[description = "Name or ID for queue position 10"]
#[autocomplete = "autocomplete_sound"]
sound_10: Option<String>,
#[description = "Name or ID for queue position 11"]
#[autocomplete = "autocomplete_sound"]
sound_11: Option<String>,
#[description = "Name or ID for queue position 12"]
#[autocomplete = "autocomplete_sound"]
sound_12: Option<String>,
#[description = "Name or ID for queue position 13"]
#[autocomplete = "autocomplete_sound"]
sound_13: Option<String>,
#[description = "Name or ID for queue position 14"]
#[autocomplete = "autocomplete_sound"]
sound_14: Option<String>,
#[description = "Name or ID for queue position 15"]
#[autocomplete = "autocomplete_sound"]
sound_15: Option<String>,
#[description = "Name or ID for queue position 16"]
#[autocomplete = "autocomplete_sound"]
sound_16: Option<String>,
#[description = "Name or ID for queue position 17"]
#[autocomplete = "autocomplete_sound"]
sound_17: Option<String>,
#[description = "Name or ID for queue position 18"]
#[autocomplete = "autocomplete_sound"]
sound_18: Option<String>,
#[description = "Name or ID for queue position 19"]
#[autocomplete = "autocomplete_sound"]
sound_19: Option<String>,
#[description = "Name or ID for queue position 20"]
#[autocomplete = "autocomplete_sound"]
sound_20: Option<String>,
#[description = "Name or ID for queue position 21"]
#[autocomplete = "autocomplete_sound"]
sound_21: Option<String>,
#[description = "Name or ID for queue position 22"]
#[autocomplete = "autocomplete_sound"]
sound_22: Option<String>,
#[description = "Name or ID for queue position 23"]
#[autocomplete = "autocomplete_sound"]
sound_23: Option<String>,
#[description = "Name or ID for queue position 24"]
#[autocomplete = "autocomplete_sound"]
sound_24: Option<String>,
#[description = "Name or ID for queue position 25"]
#[autocomplete = "autocomplete_sound"]
sound_25: Option<String>,
) -> Result<(), Error> {
let _ = ctx.defer().await;
let guild = ctx.guild().unwrap();
let channel_to_join = guild
.voice_states
.get(&ctx.author().id)
.and_then(|voice_state| voice_state.channel_id);
match channel_to_join {
Some(user_channel) => {
let (call_handler, _) = join_channel(ctx.discord(), guild.clone(), user_channel).await;
let guild_data = ctx
.data()
.guild_data(ctx.guild_id().unwrap())
.await
.unwrap();
let mut lock = call_handler.lock().await;
let query_terms = [
Some(sound_1),
Some(sound_2),
sound_3,
sound_4,
sound_5,
sound_6,
sound_7,
sound_8,
sound_9,
sound_10,
sound_11,
sound_12,
sound_13,
sound_14,
sound_15,
sound_16,
sound_17,
sound_18,
sound_19,
sound_20,
sound_21,
sound_22,
sound_23,
sound_24,
sound_25,
];
let mut sounds = vec![];
for sound in query_terms.iter().flatten() {
let search = ctx
.data()
.search_for_sound(&sound, ctx.guild_id().unwrap(), ctx.author().id, true)
.await?;
if let Some(sound) = search.first() {
sounds.push(sound.clone());
}
}
queue_audio(
&sounds,
guild_data.read().await.volume,
&mut lock,
&ctx.data().database,
)
.await
.unwrap();
ctx.say(format!("Queued {} sounds!", sounds.len())).await?;
}
None => {
ctx.say("You are not in a voice chat!").await?;
}
}
Ok(())
}
/// Loop a sound in your current voice channel /// Loop a sound in your current voice channel
#[poise::command(slash_command, rename = "loop")] #[poise::command(slash_command, rename = "loop")]
pub async fn loop_play( pub async fn loop_play(

View File

@ -2,7 +2,7 @@ use songbird;
use crate::{Context, Error}; use crate::{Context, Error};
/// Stop the bot from playing /// Stop the bot from playing and clear the play queue
#[poise::command(slash_command, rename = "stop")] #[poise::command(slash_command, rename = "stop")]
pub async fn stop_playing(ctx: Context<'_>) -> Result<(), Error> { pub async fn stop_playing(ctx: Context<'_>) -> Result<(), Error> {
let songbird = songbird::get(ctx.discord()).await.unwrap(); let songbird = songbird::get(ctx.discord()).await.unwrap();

View File

@ -102,14 +102,15 @@ SELECT name, id, public, server_id, uploader_id
let (handler, _) = join_channel(&ctx, guild, user_channel).await; let (handler, _) = join_channel(&ctx, guild, user_channel).await;
let _ = play_audio( play_audio(
&mut sound, &mut sound,
volume, volume,
&mut handler.lock().await, &mut handler.lock().await,
&data.database, &data.database,
false, false,
) )
.await; .await
.unwrap();
} }
} }
} }

View File

@ -86,6 +86,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
cmds::manage::download_file(), cmds::manage::download_file(),
cmds::manage::delete_sound(), cmds::manage::delete_sound(),
cmds::play::play(), cmds::play::play(),
cmds::play::queue_play(),
cmds::play::loop_play(), cmds::play::loop_play(),
cmds::play::soundboard(), cmds::play::soundboard(),
poise::Command { poise::Command {

View File

@ -18,7 +18,7 @@ use crate::{
}; };
pub async fn play_audio( pub async fn play_audio(
sound: &mut Sound, sound: &Sound,
volume: u8, volume: u8,
call_handler: &mut MutexGuard<'_, Call>, call_handler: &mut MutexGuard<'_, Call>,
db_pool: impl Executor<'_, Database = Database>, db_pool: impl Executor<'_, Database = Database>,
@ -39,6 +39,23 @@ pub async fn play_audio(
Ok(track_handler) Ok(track_handler)
} }
pub async fn queue_audio(
sounds: &[Sound],
volume: u8,
call_handler: &mut MutexGuard<'_, Call>,
db_pool: impl Executor<'_, Database = Database> + Copy,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
for sound in sounds {
let (a, b) = create_player(sound.playable(db_pool).await?.into());
let _ = b.set_volume(volume as f32 / 100.0);
call_handler.enqueue(a);
}
Ok(())
}
pub async fn join_channel( pub async fn join_channel(
ctx: &poise::serenity_prelude::Context, ctx: &poise::serenity_prelude::Context,
guild: Guild, guild: Guild,