274 lines
7.3 KiB
Rust
274 lines
7.3 KiB
Rust
use serenity::client::Context;
|
|
use serenity::framework::standard::Args;
|
|
use serenity::http::{AttachmentType, Http};
|
|
use serenity::model::channel::{Message, PermissionOverwrite, PermissionOverwriteType};
|
|
use serenity::model::guild::{Guild, Member};
|
|
use serenity::model::id::{ChannelId, UserId};
|
|
use serenity::model::Permissions;
|
|
|
|
use crate::error;
|
|
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 serenity::prelude::SerenityError;
|
|
|
|
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
|
|
}
|
|
|
|
pub async fn send_msg_to_player_channels(
|
|
ctx: &Context,
|
|
guild: &Guild,
|
|
global_data: &mut GlobalData,
|
|
msg_source: MessageSource,
|
|
msg: &str,
|
|
attachment: Option<Vec<AttachmentType<'_>>>,
|
|
pin: bool,
|
|
) -> error::Result<()> {
|
|
let msg_tasks = global_data
|
|
.game_state_mut()?
|
|
.player_data
|
|
.iter()
|
|
.filter(|player| filter_source_channel(player, &msg_source))
|
|
.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<Vec<Message>, 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.discord_config.host_channel,
|
|
))
|
|
.unwrap();
|
|
|
|
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(),
|
|
};
|
|
|
|
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 send_webhook_msg(
|
|
http: &Http,
|
|
webhook_id: u64,
|
|
username: &str,
|
|
profile_pic_url: Option<String>,
|
|
msg: &str,
|
|
attachment: Option<Vec<AttachmentType<'_>>>,
|
|
) -> error::Result<()> {
|
|
let webhook = http.get_webhook(webhook_id).await?;
|
|
|
|
webhook
|
|
.execute(http, false, |w| {
|
|
w.content(&msg).username(username);
|
|
|
|
if let Some(profile_pic_url) = profile_pic_url {
|
|
w.avatar_url(profile_pic_url);
|
|
}
|
|
|
|
if let Some(attachment) = attachment.clone() {
|
|
w.add_files(attachment);
|
|
}
|
|
|
|
w
|
|
})
|
|
.await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn send_webhook_msg_to_player_channels(
|
|
ctx: &Context,
|
|
guild: &Guild,
|
|
global_data: &mut GlobalData,
|
|
msg_source: MessageSource,
|
|
msg: &str,
|
|
attachment: 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 => None,
|
|
};
|
|
|
|
let msg_tasks = global_data
|
|
.game_state_mut()?
|
|
.player_data
|
|
.iter()
|
|
.filter(|player| filter_source_channel(player, &msg_source))
|
|
.map(|player_data| {
|
|
send_webhook_msg(
|
|
&ctx.http,
|
|
player_data.channel_webhook_id,
|
|
&msg_username,
|
|
profile_pic.clone(),
|
|
msg,
|
|
attachment.clone(),
|
|
)
|
|
});
|
|
|
|
let msgs: Result<(), WoxlfError> = futures::future::join_all(msg_tasks)
|
|
.await
|
|
.into_iter()
|
|
.collect();
|
|
|
|
msgs?;
|
|
|
|
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 host_channel_username = format!("{} ({})", msg_username, source);
|
|
|
|
send_webhook_msg(
|
|
&ctx.http,
|
|
global_data.cfg.discord_config.host_webhook_id,
|
|
&host_channel_username,
|
|
profile_pic,
|
|
msg,
|
|
attachment,
|
|
)
|
|
.await?;
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn add_user_to_game(
|
|
ctx: &Context,
|
|
guild: &Guild,
|
|
global_data: &mut GlobalData,
|
|
discord_user: &Member,
|
|
first_name: Option<String>,
|
|
last_name: Option<String>,
|
|
) -> error::Result<PlayerData> {
|
|
if first_name == None && last_name == None {
|
|
return Err(WoxlfError::RanOutOfCodenames);
|
|
}
|
|
|
|
let codename = global_data
|
|
.templates()?
|
|
.build_name(global_data, first_name, last_name)
|
|
.unwrap();
|
|
|
|
let channel = guild
|
|
.create_channel(&ctx.http, |c| {
|
|
c.category(&ChannelId::from(global_data.cfg.discord_config.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 webhook = channel
|
|
.create_webhook(
|
|
&ctx.http,
|
|
format!("{}'s Woxlf Webhook", discord_user.display_name()),
|
|
)
|
|
.await?;
|
|
|
|
let player_data = PlayerData {
|
|
channel: channel.id.0,
|
|
discord_id: discord_user.user.id.0,
|
|
vote_target: None,
|
|
codename,
|
|
channel_webhook_id: webhook.id.0,
|
|
profile_pic_url: global_data.get_profile_pic_url().await?,
|
|
};
|
|
|
|
global_data
|
|
.game_state_mut()?
|
|
.player_data
|
|
.push(player_data.clone());
|
|
|
|
Ok(player_data)
|
|
}
|
|
|
|
pub async fn parse_duration_arg(args: &mut Args) -> error::Result<PhaseDuration> {
|
|
match args.single::<PhaseDuration>() {
|
|
Ok(d) => Ok(d),
|
|
Err(_) => Err(WoxlfError::DurationParseError),
|
|
}
|
|
}
|