use serenity::prelude::Context; use serenity::model::prelude::{Message, UserId}; use serenity::framework::standard::{CommandResult, Args}; use serenity::framework::StandardFramework; use serenity::framework::standard::macros::{command, group}; use crate::data::{GlobalData, BotConfig, PlayerData}; use rand::Rng; use serenity::model::guild::{Member, Guild}; use serenity::model::id::ChannelId; use serenity::model::Permissions; use serenity::model::channel::{PermissionOverwrite, PermissionOverwriteType}; use serenity::utils::MessageBuilder; #[group] #[commands(start)] struct Host; fn generate_codename(config: &BotConfig) -> String { let mut rng = rand::thread_rng(); let occupation = &config.occupation[rng.gen_range(0..config.occupation.len())]; let adj = &config.adjective[rng.gen_range(0..config.adjective.len())]; format!("{} {}", adj, occupation) } async fn add_user_to_game(ctx: &Context, guild: &Guild, global_data: &mut GlobalData, discord_user: &Member) { let mut codename = generate_codename(&global_data.cfg); while global_data.game_state.codename_exists(&mut codename) { codename = generate_codename(&global_data.cfg); } let channel = guild.create_channel(&ctx.http, |c| { c .category(&ChannelId::from(global_data.cfg.category)) .name(format!("{}'s Channel", discord_user.display_name())) }).await.unwrap(); let allow = Permissions::SEND_MESSAGES | Permissions::READ_MESSAGE_HISTORY | Permissions::READ_MESSAGE_HISTORY; let overwrite = PermissionOverwrite { allow, deny: Default::default(), kind: PermissionOverwriteType::Member(discord_user.user.id), }; channel.create_permission(&ctx.http, &overwrite).await.unwrap(); let msg = channel.send_message(&ctx.http, |m| { m.content(MessageBuilder::new() .push("Welcome ") .mention(discord_user) .push_line(" to your WOxlf Terminal. You may use this terminal to communicate to other subjects.") .push_line("You will also use this terminal for choosing one of your fellow subjects for termination.") .push_line("Happy testing :)") .push_line("") .push("SUBJECT CODENAME: ") .push_line(&codename) ) }).await.unwrap(); channel.pin(&ctx.http, msg.id).await.unwrap(); let player_data = PlayerData { discord_id: discord_user.user.id.0, codename: codename }; global_data.game_state.player_channels.insert(channel.id.0, player_data); } #[command] #[only_in(guilds)] #[allowed_roles("wolfx host")] async fn start(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { msg.channel_id.say(&ctx.http, "Starting game").await?; let mut data = ctx.data.write().await; let global_data = data.get_mut::().unwrap(); let guild = msg.guild(&ctx.cache).await.unwrap(); let mut global_data = global_data.lock().await; global_data.game_state.clear(); for player in args.iter::() { if let Ok(player) = player { if let Some(discord_user) = guild.members.get(&UserId::from(player)) { add_user_to_game(ctx, &guild, &mut global_data, &discord_user).await; } else { msg.reply(&ctx.http,format!("User {} is invalid or not in this server!", player)).await.unwrap(); break; } } } Ok(()) } pub fn command_framework() -> StandardFramework { StandardFramework::new() .configure(|c| { c.prefix("!") }) .group(&HOST_GROUP) }