use crate::error; use crate::game::global_data::GlobalData; use crate::game::player_data::PlayerData; use serenity::client::Context; use serenity::http::Http; use serenity::model::guild::Guild; use serenity::model::id::UserId; use serenity::model::prelude::AttachmentType; use serenity::utils::MessageBuilder; #[derive(Debug, Clone)] pub enum MessageSource { Player(Box), Host, Automated, } #[derive(Debug, Clone)] pub enum MessageDest { PlayerChannel(Box), PlayerDm(Box), Broadcast, } fn filter_source_channel(player_data: &&PlayerData, msg_source: &MessageSource) -> bool { if let MessageSource::Player(source_player) = &msg_source { if source_player.channel == player_data.channel { return false; } } true } async fn send_webhook_msg( http: &Http, webhook_id: u64, username: &str, profile_pic_url: Option, msg: &str, attachments: &Option>>, ) -> error::Result<()> { let webhook = http.get_webhook(webhook_id).await?; webhook .execute(http, false, move |w| { w.content(&msg).username(username); if let Some(profile_pic_url) = profile_pic_url { w.avatar_url(profile_pic_url); } if let Some(attachments) = attachments { w.add_files(attachments.clone()); } w }) .await?; Ok(()) } async fn send_private_message( http: &Http, src_username: &str, dest: UserId, msg: &str, attachments: &Option>>, ) -> error::Result<()> { let dest_user = dest.to_user(http).await?; let mut dm_message = MessageBuilder::new(); dm_message.push_bold_line_safe(format!("{} has sent you a DM:", src_username)); dm_message.push(msg); dest_user .dm(http, |msg| { msg.content(dm_message); if let Some(attachments) = attachments { msg.add_files(attachments.clone()); } msg }) .await?; Ok(()) } async fn send_to_host_channel( http: &Http, guild: &Guild, global_data: &mut GlobalData, msg_username: &str, msg_source: MessageSource, msg_dest: MessageDest, profile_pic_url: Option, msg: &str, attachments: &Option>>, ) -> error::Result<()> { let source = match &msg_source { MessageSource::Player(player_data) => { let name = guild .members .get(&UserId::from(player_data.discord_id)) .unwrap() .display_name(); name.to_string() } MessageSource::Host => "Host".to_string(), MessageSource::Automated => "Automated".to_string(), }; let dest = match &msg_dest { MessageDest::PlayerChannel(p) | MessageDest::PlayerDm(p) => { let name = guild .members .get(&UserId::from(p.discord_id)) .unwrap() .display_name(); format!(" to {} ({})", p.codename, name) } MessageDest::Broadcast => "".to_string(), }; let host_channel_username = format!("{} ({}){}", msg_username, source, dest); send_webhook_msg( http, global_data.cfg.discord_config.host_webhook_id, &host_channel_username, profile_pic_url, msg, attachments, ) .await?; Ok(()) } pub async fn dispatch_message( ctx: &Context, guild: &Guild, global_data: &mut GlobalData, msg_source: MessageSource, msg_dest: MessageDest, msg: &str, attachments: Option>>, ) -> error::Result<()> { let msg_username = match &msg_source { MessageSource::Player(p) => p.codename.clone(), MessageSource::Host => "Woxlf".to_string(), MessageSource::Automated => "Woxlf System Message".to_string(), }; let profile_pic = match &msg_source { MessageSource::Player(p) => Some(p.profile_pic_url.clone()), MessageSource::Host | MessageSource::Automated => { Some(global_data.game_cfg()?.bot_profile_pic.clone()) } }; let msg_tasks: Vec<&PlayerData> = global_data .game_state_mut()? .player_data .iter() .filter(|player| filter_source_channel(player, &msg_source)) .collect(); for player_data in msg_tasks { match &msg_dest { MessageDest::PlayerChannel(dest_player) => { if dest_player.discord_id == player_data.discord_id { send_webhook_msg( &ctx.http, player_data.channel_webhook_id, &msg_username, profile_pic.clone(), msg, &attachments, ) .await?; } } MessageDest::PlayerDm(dest_player) => { send_private_message( &ctx.http, &msg_username, UserId(dest_player.discord_id), msg, &attachments, ) .await? } MessageDest::Broadcast => { send_webhook_msg( &ctx.http, player_data.channel_webhook_id, &msg_username, profile_pic.clone(), msg, &attachments, ) .await? } } } send_to_host_channel( &ctx.http, guild, global_data, &msg_username, msg_source, msg_dest, profile_pic, msg, &attachments, ) .await?; Ok(()) }