use serenity::client::Context; use serenity::framework::standard::Args; use serenity::http::AttachmentType; use serenity::model::channel::{Message, PermissionOverwrite, PermissionOverwriteType}; use serenity::model::guild::{Guild, Member}; use serenity::model::id::{ChannelId, UserId}; use serenity::model::Permissions; use serenity::utils::MessageBuilder; use crate::error::WoxlfError; use crate::game::game_state::PhaseDuration; use crate::game::global_data::GlobalData; use crate::game::player_data::PlayerData; use crate::game::MessageSource; use crate::{error, game}; use serenity::prelude::SerenityError; pub async fn send_msg_to_player_channels( ctx: &Context, guild: &Guild, global_data: &mut GlobalData, msg_source: MessageSource, msg: &str, attachment: Option>>, pin: bool, ) -> error::Result<()> { let msg_tasks = global_data .game_state_mut()? .player_data .iter() .filter(|player_data| { if let MessageSource::Player(channel_id) = msg_source { if channel_id == player_data.channel { return false; } } true }) .map(|player_data| { let channel = guild .channels .get(&ChannelId::from(player_data.channel)) .unwrap(); channel.send_message(&ctx.http, |m| { m.content(&msg); if let Some(attachment) = attachment.clone() { m.add_files(attachment); } m }) }); let msgs: Result, SerenityError> = futures::future::join_all(msg_tasks) .await .into_iter() .collect(); let msgs = msgs?; if pin { let pin_tasks = msgs.iter().map(|msg| msg.pin(&ctx.http)); let pins: Result<(), SerenityError> = futures::future::join_all(pin_tasks) .await .into_iter() .collect(); pins?; } let host_channel = guild .channels .get(&ChannelId::from(global_data.cfg.host_channel)) .unwrap(); let source = match msg_source { MessageSource::Player(channel_id) => { let discord_id = global_data .game_state_mut()? .get_player_from_channel(channel_id) .unwrap() .discord_id; let name = guild .members .get(&UserId::from(discord_id)) .unwrap() .display_name(); name.to_string() } MessageSource::Host => "Host".to_string(), MessageSource::Automated => "Automated".to_string(), }; host_channel .send_message(&ctx.http, |m| { m.content(format!("({}): {}", source, msg)); if let Some(attachment) = attachment { m.add_files(attachment); } m }) .await?; Ok(()) } pub async fn add_user_to_game( ctx: &Context, guild: &Guild, global_data: &mut GlobalData, discord_user: &Member, ) -> error::Result<()> { let mut codename = game::generate_codename(&global_data.cfg); while global_data.game_state_mut()?.codename_exists(&codename) { codename = game::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?; let allow = Permissions::SEND_MESSAGES | Permissions::READ_MESSAGE_HISTORY | Permissions::READ_MESSAGES; let overwrite = PermissionOverwrite { allow, deny: Default::default(), kind: PermissionOverwriteType::Member(discord_user.user.id), }; channel.create_permission(&ctx.http, &overwrite).await?; 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_line("Do $help to see all commands.") .push_line("") .push("SUBJECT CODENAME: ") .push_line(&codename) .push(global_data.print_game_status()) ) }).await?; channel.pin(&ctx.http, msg.id).await?; let player_data = PlayerData { channel: channel.id.0, discord_id: discord_user.user.id.0, vote_target: None, codename, }; global_data.game_state_mut()?.player_data.push(player_data); Ok(()) } pub fn build_system_message(msg: &str) -> String { MessageBuilder::new() .push_bold_line("\\*\\*IMPORTANT wOxlf SYSTEM MESSAGE\\*\\*") .push_line("") .push_line(msg) .push_line("") .push_bold_line("\\*\\*END OF SYSTEM MESSAGE\\*\\*") .build() } pub async fn parse_duration_arg(args: &mut Args) -> error::Result { match args.single::() { Ok(d) => Ok(d), Err(_) => Err(WoxlfError::DurationParseError), } }