wOxlf/src/game/message_router.rs

228 lines
5.8 KiB
Rust

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<PlayerData>),
Host,
Automated,
}
#[derive(Debug, Clone)]
pub enum MessageDest {
PlayerChannel(Box<PlayerData>),
PlayerDm(Box<PlayerData>),
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<String>,
msg: &str,
attachments: &Option<Vec<AttachmentType<'_>>>,
) -> 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<Vec<AttachmentType<'_>>>,
) -> 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<String>,
msg: &str,
attachments: &Option<Vec<AttachmentType<'_>>>,
) -> 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<Vec<AttachmentType<'_>>>,
) -> 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(())
}