use std::error::Error; use serenity::all::{ Context, Message, }; use crate::{ commands::playback::songbird, util, PoiseContext, }; /// Mute audio (don't pause). #[poise::command(prefix_command, guild_only, category = "playback")] pub async fn mute(ctx: PoiseContext<'_>) -> anyhow::Result<()> { let (_sb, call) = songbird(ctx).await?; let mut call = call.lock().await; call.mute(true).await?; Ok(()) } /// Unmute audio. #[poise::command(prefix_command, guild_only, category = "playback")] pub async fn unmute(ctx: PoiseContext<'_>) -> anyhow::Result<()> { let (_sb, call) = songbird(ctx).await?; let mut call = call.lock().await; call.mute(true).await?; Ok(()) } #[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] struct PercentArg(f64); lazy_static::lazy_static! { static ref ARG_PCT: regex::Regex = regex::Regex::new(r#"(\d+(?:\.\d+)?)\s*%?(.*)"#).unwrap(); } #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, thiserror::Error)] #[error("expected a number with an optional trailing %")] struct NonPctError; #[poise::async_trait] impl<'a> poise::PopArgument<'a> for PercentArg { async fn pop_from( args: &'a str, attachment_index: usize, _ctx: &Context, _msg: &Message, ) -> Result<(&'a str, usize, Self), (Box, Option)> { let Some(mtch) = ARG_PCT.captures(args) else { return Err((Box::new(NonPctError), None)); }; let pct = mtch.get(1).unwrap().as_str().parse::().unwrap(); let prop = pct / 100.; let rest = mtch.get(2).unwrap().as_str(); Ok((rest, attachment_index, Self(prop))) } } /// Set volume by percent. #[poise::command(prefix_command, guild_only, category = "playback")] pub async fn volume(ctx: PoiseContext<'_>, volume: Option) -> anyhow::Result<()> { let Some(volume) = volume else { let cur_vol = util::volume(ctx).await * 100.; util::reply(ctx, format!("{cur_vol:.0}%")).await?; return Ok(()); }; { let data = ctx.serenity_context().data.read().await; let vol = data.get::().unwrap(); vol.insert(util::guild_id(ctx)?, volume.0); } let (_sb, call) = songbird(ctx).await?; let call = call.lock().await; call.queue().modify_queue(|q| { for elt in q { elt.set_volume(volume.0 as _)?; } anyhow::Ok(()) }) }