use std::sync::Arc; use reqwest::Url; use serenity::all::UserId; use serenity::client::Cache; use serenity::model::prelude::{GuildId, ChannelId}; use songbird::Songbird; use crate::error::{SirenResult, Error as SirenError}; pub mod mute; pub mod pause; pub mod play; pub mod resume; pub mod skip; pub mod stop; pub mod volume; /** * Finds a voice channel that the user is currently in, and attempts to join it. */ pub async fn join_voice_channel( cache: &Arc, manager: &Arc, guild_id: &GuildId, user_id: &UserId, ) -> SirenResult { let channel_id = find_voice_channel(cache, guild_id, user_id)?; log::debug!("<{}> Joining channel {}", guild_id.get(), channel_id.get()); manager .join(guild_id.to_owned(), channel_id.to_owned()) .await?; Ok(channel_id) } /** * Leaves a voice channel. */ pub async fn leave_voice_channel(manager: &Arc, guild_id: &GuildId) -> SirenResult<()> { if manager.get(guild_id.to_owned()).is_some() { log::debug!("<{}> Disconnecting from channel", guild_id.get()); manager.remove(*guild_id).await?; } Ok(()) } /** * Validates whether the given string is a properly formatted URL. * * Returns `true` if the input string is a valid URL, otherwise `false`. */ fn is_valid_url(url: &str) -> bool { Url::parse(url).is_ok() } /** * Finds a voice channel that the user is currently in. */ fn find_voice_channel( cache: &Arc, guild_id: &GuildId, user_id: &UserId, ) -> SirenResult { let guild = match guild_id.to_guild_cached(cache) { Some(g) => g, None => return Err(SirenError::new(404, "Guild not found".to_string())), }; match guild .voice_states .get(&user_id) .and_then(|voice_state| voice_state.channel_id) { Some(channel) => Ok(channel), None => Err(SirenError::new( 400, "User is not in a voice channel".to_string(), )), } }