use poise::serenity_prelude::{ model::channel::Channel, ActionRowComponent, Activity, Context, CreateActionRow, FullEvent, Interaction, }; #[cfg(feature = "metrics")] use crate::metrics::GREET_COUNTER; use crate::{ cmds::search::SoundPager, models::{ guild_data::{AllowGreet, CtxGuildData}, join_sound::JoinSoundCtx, sound::Sound, }, utils::{join_channel, play_audio, play_from_query}, Data, Error, }; pub async fn listener(ctx: &Context, event: &FullEvent, data: &Data) -> Result<(), Error> { match event { FullEvent::Ready { .. } => { ctx.set_activity(Activity::watching("for /play")).await; } FullEvent::VoiceStateUpdate { old, new, .. } => { if let Some(past_state) = old { if let (Some(guild_id), None) = (past_state.guild_id, new.channel_id) { if let Some(channel_id) = past_state.channel_id { if let Some(Channel::Guild(channel)) = channel_id.to_channel_cached(&ctx.cache) { if channel.members(&ctx).await.map(|m| m.len()).unwrap_or(0) <= 1 { let songbird = songbird::get(ctx).await.unwrap(); let _ = songbird.remove(guild_id).await; } } } } } else if let (Some(guild_id), Some(user_channel)) = (new.guild_id, new.channel_id) { if let Some(guild) = ctx.cache.guild(guild_id) { let guild_data_opt = data.guild_data(guild.id).await; if let Ok(guild_data) = guild_data_opt { let volume; let allowed_greets; { let read = guild_data.read().await; volume = read.volume; allowed_greets = read.allow_greets; } if allowed_greets != AllowGreet::Disabled { if let Some(join_id) = data .join_sound( new.user_id, new.guild_id, allowed_greets == AllowGreet::GuildOnly, ) .await { let mut sound = sqlx::query_as_unchecked!( Sound, " SELECT name, id, public, server_id, uploader_id FROM sounds WHERE id = ?", join_id ) .fetch_one(&data.database) .await .unwrap(); let (handler, _) = join_channel(&ctx, guild, user_channel).await; #[cfg(feature = "metrics")] GREET_COUNTER.inc(); play_audio( &mut sound, volume, &mut handler.lock().await, &data.database, false, ) .await .unwrap(); } } } } } } FullEvent::InteractionCreate { interaction } => match interaction { Interaction::MessageComponent(component) => { if let Some(guild_id) = component.guild_id { if let Ok(()) = SoundPager::handle_interaction(ctx, &data, component).await { } else { let mode = component.data.custom_id.as_str(); match mode { "#stop" => { component .create_interaction_response(ctx, |r| { r.kind(InteractionResponseType::DeferredUpdateMessage) }) .await .unwrap(); let songbird = songbird::get(ctx).await.unwrap(); let call_opt = songbird.get(guild_id); if let Some(call) = call_opt { let mut lock = call.lock().await; lock.stop(); } } "#loop" | "#queue" | "#instant" => { component .create_interaction_response(ctx, |r| { r.kind(InteractionResponseType::UpdateMessage) .interaction_response_data(|d| { let mut c = vec![]; for action_row in &component.message.components { let mut a: CreateActionRow = Default::default(); // These are always buttons for component in &action_row.components { match component { ActionRowComponent::Button(button) => { a.create_button(|b| { if let Some(label) = &button.label { b.label(label); } if let Some(emoji) = &button.emoji { b.emoji(emoji.clone()); } if let Some(custom_id) = &button.custom_id { if custom_id .starts_with('#') { b.custom_id(custom_id) .disabled( custom_id == "#mode" || custom_id == mode, ); } else { b.custom_id(format!( "{}{}", custom_id .split('#') .next() .unwrap(), mode )); } } b.style(button.style); b }); } _ => {} } } c.push(a); } d.set_components(c) }) }) .await .unwrap(); } id_mode => { component .create_interaction_response(ctx, |r| { r.kind(InteractionResponseType::DeferredUpdateMessage) }) .await .unwrap(); let mut it = id_mode.split('#'); let id = it.next().unwrap(); let mode = it.next().unwrap_or("instant"); play_from_query( &ctx, &data, guild_id.to_guild_cached(&ctx).unwrap(), component.user.id, None, id.split('#').next().unwrap(), mode == "loop", ) .await; } } } } } _ => {} }, _ => {} } Ok(()) }