diff --git a/src/commands/slur.rs b/src/commands/slur.rs index f0ff564..385d480 100644 --- a/src/commands/slur.rs +++ b/src/commands/slur.rs @@ -1,5 +1,5 @@ -use crate::{Context, Error}; use crate::serenity; +use crate::{Context, Error}; use rand::seq::IteratorRandom; use std::{ fs::File, @@ -8,22 +8,21 @@ use std::{ /// Basically a ping command #[poise::command(slash_command)] -pub(crate) async fn slur( - ctx: Context<'_>, -) -> Result<(), Error> { - let file = File::open("quotes.txt") - .unwrap_or_else(|_e| panic!("Quote file missing.")); // Open the quotes file +pub(crate) async fn slur(ctx: Context<'_>) -> Result<(), Error> { + let file = File::open("quotes.txt").unwrap_or_else(|_e| panic!("Quote file missing.")); // Open the quotes file let file = BufReader::new(file); // Read the quotes file - let quotes = file.lines() - .map(|res| res.expect("Failed to read line.")); - let quote = quotes.choose(&mut rand::thread_rng()) + let quotes = file.lines().map(|res| res.expect("Failed to read line.")); + let quote = quotes + .choose(&mut rand::thread_rng()) .expect("No lines in file."); // Pick a random quote - ctx.send(|f| f - .embed(|f| f - .title("DMBrandon Sez:") - .description(format!("\"{}\"", quote)) - .color(serenity::Colour::GOLD) - )).await?; // Send embed with team picks + ctx.send(|f| { + f.embed(|f| { + f.title("DMBrandon Sez:") + .description(format!("\"{}\"", quote)) + .color(serenity::Colour::GOLD) + }) + }) + .await?; // Send embed with team picks Ok(()) } diff --git a/src/commands/team.rs b/src/commands/team.rs index 0ee839e..2ccde8a 100644 --- a/src/commands/team.rs +++ b/src/commands/team.rs @@ -4,12 +4,16 @@ use std::string::String; use poise::serenity_prelude::{Guild, Member, UserId, VoiceState}; use rand::seq::SliceRandom; -use crate::{Context, Error}; use crate::serenity; +use crate::{Context, Error}; /// Return a string of pingable IDs from a slice of string UserIds fn team_to_ping(team: &[&String]) -> String { - return team.iter().map(|o| format!("<@{}>", o)).collect::>().join(", "); + return team + .iter() + .map(|o| format!("<@{}>", o)) + .collect::>() + .join(", "); } /// Splits up players for custom matches @@ -18,76 +22,101 @@ pub(crate) async fn team( ctx: Context<'_>, #[description = "Your order voice channel"] #[rename = "order"] - #[channel_types("Voice")] order_channel: serenity::Channel, // Channel to pick all members from + #[channel_types("Voice")] + order_channel: serenity::Channel, // Channel to pick all members from #[description = "Your chaos voice channel"] #[rename = "chaos"] - #[channel_types("Voice")] chaos_channel: serenity::Channel, // Channel to move chaos team members into + #[channel_types("Voice")] + chaos_channel: serenity::Channel, // Channel to move chaos team members into #[description = "Team size"] - #[min = 1] size: u8, // Number of members on each team + #[min = 1] + size: u8, // Number of members on each team ) -> Result<(), Error> { let mut voice_states: HashMap = ctx.guild().unwrap().voice_states; // Get hashmap of users' voice states within the guild voice_states.retain(|_, state: &mut VoiceState| state.channel_id == Some(order_channel.id())); // Drop users not active in requested voice channel from hashmap - if voice_states.keys().len() < size as usize * 2 { // Make sure there are enough members in the voice channel - ctx.send(|f| f - .embed(|f| f - .title(format!("Custom {}v{} Teams", size, size)) - .description("You don't have enough friends for that, idiot.") - .color(serenity::Colour::RED) - )).await?; // Insult the user for not having enough friends + if voice_states.keys().len() < size as usize * 2 { + // Make sure there are enough members in the voice channel + ctx.send(|f| { + f.embed(|f| { + f.title(format!("Custom {}v{} Teams", size, size)) + .description("You don't have enough friends for that, idiot.") + .color(serenity::Colour::RED) + }) + }) + .await?; // Insult the user for not having enough friends return Ok(()); // Break out early if there are not enough members } let uuid_team: u64 = ctx.id(); // Grab context ID for action row let users: Vec = Vec::from_iter(voice_states.keys().map(|u| u.to_string())); // Get vec of PIDs - let players: Vec<&String> = users.choose_multiple(&mut rand::thread_rng(), size as usize * 2).collect(); // Pick players randomly into slice + let players: Vec<&String> = users + .choose_multiple(&mut rand::thread_rng(), size as usize * 2) + .collect(); // Pick players randomly into slice let (order, chaos) = players.split_at(players.len() / 2); // Split slice into two teams - ctx.send(|f| f - .embed(|f| f - .title(format!("Custom {}v{} Teams", size, size)) - .description("VER") - .field("Order", team_to_ping(order), false) - .field("Chaos", team_to_ping(chaos), false) - .color(serenity::Colour::DARK_GREEN) - ).components(|c| c // Create an action row with button - .create_action_row(|a| a - .create_button(|b| b - .style(serenity::ButtonStyle::Primary) - .label("Swap Channels") - .custom_id(uuid_team) // Use the context ID as button ID - ) - ) - )).await?; // Send embed with team picks + ctx.send(|f| { + f.embed(|f| { + f.title(format!("Custom {}v{} Teams", size, size)) + .description("VER") + .field("Order", team_to_ping(order), false) + .field("Chaos", team_to_ping(chaos), false) + .color(serenity::Colour::DARK_GREEN) + }) + .components(|c| { + c // Create an action row with button + .create_action_row(|a| { + a.create_button( + |b| { + b.style(serenity::ButtonStyle::Primary) + .label("Swap Channels") + .custom_id(uuid_team) + }, // Use the context ID as button ID + ) + }) + }) + }) + .await?; // Send embed with team picks while let Some(mci) = serenity::CollectComponentInteraction::new(ctx) // Handle the interaction - .await { + .await + { let guild: Guild = ctx.guild().unwrap(); // Grab guild from context for user in chaos { let member: Member = guild.member(ctx, UserId(user.parse().unwrap())).await?; // Get the member in the correct guild - member.move_to_voice_channel(ctx, chaos_channel.id()).await?; // Move the member to the correct voice channel + member + .move_to_voice_channel(ctx, chaos_channel.id()) + .await?; // Move the member to the correct voice channel } - mci.create_interaction_response(ctx, |ir| { // Edit embed + mci.create_interaction_response(ctx, |ir| { + // Edit embed ir.kind(serenity::InteractionResponseType::UpdateMessage) - .interaction_response_data(|f| f - .embed(|f| f - .title(format!("Custom {}v{} Teams", size, size)) - .description("VVGO VVW VVX") - .field("Order", team_to_ping(order), false) - .field("Chaos", team_to_ping(chaos), false) - .color(serenity::Colour::DARK_GREEN) - ).components(|c| c // Create an action row with button - .create_action_row(|a| a - .create_button(|b| b + .interaction_response_data(|f| { + f.embed(|f| { + f.title(format!("Custom {}v{} Teams", size, size)) + .description("VVGO VVW VVX") + .field("Order", team_to_ping(order), false) + .field("Chaos", team_to_ping(chaos), false) + .color(serenity::Colour::DARK_GREEN) + }) + .components(|c| { + c // Create an action row with button + .create_action_row(|a| { + a.create_button( + |b| { + b .disabled(true) // with disabled button .style(serenity::ButtonStyle::Primary) .label("Quit Sibelius") // and new text - .custom_id(uuid_team) // Use the context ID as button ID - ) - ) - )) - }).await?; + .custom_id(uuid_team) + }, // Use the context ID as button ID + ) + }) + }) + }) + }) + .await?; } Ok(()) } diff --git a/src/main.rs b/src/main.rs index 6cfc594..e3f24a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,23 +11,24 @@ type Context<'a> = poise::Context<'a, Data, Error>; async fn main() { let framework = poise::Framework::builder() .options(poise::FrameworkOptions { - commands: vec![ - commands::slur::slur(), - commands::team::team(), - ], // IntelliJ doesn't like this, but it's fine. + commands: vec![commands::slur::slur(), commands::team::team()], // IntelliJ doesn't like this, but it's fine. ..Default::default() }) - .token(std::env::var("DISCORD_TOKEN") - .expect("Missing DISCORD_TOKEN")) + .token(std::env::var("DISCORD_TOKEN").expect("Missing DISCORD_TOKEN")) .intents(serenity::GatewayIntents::non_privileged()) // Set intents for Discord dev portal .setup(|ctx, _ready, framework| { Box::pin(async move { poise::builtins::register_in_guild( ctx, &framework.options().commands, - serenity::GuildId(std::env::var("GUILD_ID") - .expect("Missing GUILD_ID") // Get GID from env and parse - .parse::().unwrap())).await?; // Update slash commands in GID + serenity::GuildId( + std::env::var("GUILD_ID") + .expect("Missing GUILD_ID") // Get GID from env and parse + .parse::() + .unwrap(), + ), + ) + .await?; // Update slash commands in GID Ok(Data {}) }) });