225 lines
6.6 KiB
Rust
225 lines
6.6 KiB
Rust
use crate::game::global_data::GlobalData;
|
|
use crate::game::message_router::{
|
|
dispatch_message, Median, MessageDest, MessageSource, WoxlfMessage,
|
|
};
|
|
use crate::game::Phase;
|
|
use serenity::client::Context;
|
|
use serenity::framework::standard::macros::{command, group};
|
|
use serenity::framework::standard::{Args, CommandResult};
|
|
use serenity::model::channel::Message;
|
|
use serenity::model::id::{ChannelId, UserId};
|
|
use serenity::utils::MessageBuilder;
|
|
|
|
#[group]
|
|
#[commands(vote, status, players, whisper)]
|
|
struct Player;
|
|
|
|
#[command]
|
|
#[only_in(guilds)]
|
|
#[description = "vote another subject for termination. $vote <code_name>"]
|
|
async fn vote(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
|
|
let mut data = ctx.data.write().await;
|
|
let global_data = data.get_mut::<GlobalData>().unwrap();
|
|
let guild = msg.guild(&ctx.cache).unwrap();
|
|
|
|
let mut global_data = global_data.lock().await;
|
|
|
|
if global_data.game_state_mut()?.current_phase != Phase::Day {
|
|
msg.reply(
|
|
&ctx.http,
|
|
format!(
|
|
"You can only vote during the {} phase.",
|
|
global_data.game_cfg()?.vote_phase_name
|
|
),
|
|
)
|
|
.await
|
|
.unwrap();
|
|
return Ok(());
|
|
}
|
|
|
|
if global_data
|
|
.game_state_mut()?
|
|
.get_player_from_channel(msg.channel_id.0)
|
|
.is_some()
|
|
{
|
|
let target_player = global_data
|
|
.game_state_mut()?
|
|
.get_player_by_codename(args.rest());
|
|
|
|
if let Some(target_player) = target_player {
|
|
let vote_channel = guild
|
|
.channels
|
|
.get(&ChannelId::from(
|
|
global_data.cfg.discord_config.vote_channel,
|
|
))
|
|
.unwrap();
|
|
|
|
let player_data = global_data
|
|
.game_state_mut()?
|
|
.get_player_from_channel_mut(msg.channel_id.0)
|
|
.unwrap();
|
|
|
|
player_data.cast_vote(target_player.discord_id);
|
|
|
|
// borrow as immutable
|
|
let player_data = global_data
|
|
.game_state()?
|
|
.get_player_from_channel(msg.channel_id.0)
|
|
.unwrap();
|
|
|
|
let vote_msg = global_data.templates()?.build_vote_message(
|
|
&global_data,
|
|
player_data,
|
|
&target_player,
|
|
)?;
|
|
|
|
vote_channel
|
|
.id()
|
|
.send_message(&ctx.http, |m| m.content(vote_msg))
|
|
.await?;
|
|
} else {
|
|
msg.reply(&ctx.http, "Target not found!").await.unwrap();
|
|
}
|
|
} else {
|
|
msg.reply(
|
|
&ctx.http,
|
|
"This command needs to be run in a game channel, goober",
|
|
)
|
|
.await?;
|
|
}
|
|
|
|
global_data.save_game_state().unwrap();
|
|
Ok(())
|
|
}
|
|
|
|
#[command]
|
|
#[only_in(guilds)]
|
|
#[description = "Get the game status."]
|
|
async fn status(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
|
let mut data = ctx.data.write().await;
|
|
let global_data = data.get_mut::<GlobalData>().unwrap();
|
|
|
|
let mut global_data = global_data.lock().await;
|
|
|
|
let mut msg_builder = MessageBuilder::new();
|
|
|
|
msg_builder.push(
|
|
global_data
|
|
.templates()?
|
|
.build_satus_message(&global_data)
|
|
.unwrap(),
|
|
);
|
|
|
|
if global_data.game_state_mut()?.current_phase == Phase::Day {
|
|
msg_builder.push_line(
|
|
global_data
|
|
.templates()?
|
|
.build_vote_tally(&global_data)
|
|
.unwrap(),
|
|
);
|
|
}
|
|
|
|
msg.reply(&ctx.http, msg_builder.build()).await.unwrap();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[command]
|
|
#[only_in(guilds)]
|
|
#[description = "Get the other players in the game."]
|
|
async fn players(ctx: &Context, msg: &Message, _args: Args) -> CommandResult {
|
|
let data = ctx.data.read().await;
|
|
let global_data = data.get::<GlobalData>().unwrap();
|
|
|
|
let global_data = global_data.lock().await;
|
|
|
|
let mut msg_builder = MessageBuilder::new();
|
|
|
|
msg_builder.push_line(&global_data.game_cfg()?.player_group_name);
|
|
|
|
for player in &global_data.game_state()?.player_data {
|
|
let alive_status = if !player.alive { " (Dead) " } else { "" };
|
|
|
|
msg_builder
|
|
.push("* ")
|
|
.push(&player.codename)
|
|
.push(alive_status);
|
|
|
|
if msg.channel_id.0 == global_data.cfg.discord_config.host_channel {
|
|
let guild = msg.guild(&ctx.cache).unwrap();
|
|
let member = guild.members.get(&UserId::from(player.discord_id)).unwrap();
|
|
msg_builder.push_line(format!(
|
|
" ({}) [{} {}]",
|
|
member.display_name(),
|
|
player.role,
|
|
player.role.seer_color()
|
|
));
|
|
} else {
|
|
msg_builder.push_line("");
|
|
}
|
|
}
|
|
|
|
msg.reply(&ctx.http, msg_builder.build()).await.unwrap();
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[command]
|
|
#[aliases("pm", "w")]
|
|
#[description = "Send a private message to another player."]
|
|
async fn whisper(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
|
|
let data = ctx.data.read().await;
|
|
let global_data = data.get::<GlobalData>().unwrap();
|
|
let mut global_data = global_data.lock().await;
|
|
|
|
if !global_data.game_cfg()?.whispers_allowed {
|
|
msg.reply(&ctx.http, "No private messages are allowed in this game")
|
|
.await?;
|
|
return Ok(());
|
|
}
|
|
|
|
if args.len() < 2 {
|
|
msg.reply(&ctx.http, "Need a recipient and message!")
|
|
.await?;
|
|
} else {
|
|
let target = args.single::<String>()?;
|
|
let pm = args.rest();
|
|
|
|
let src_player = match global_data
|
|
.game_state()?
|
|
.get_player_from_discord_id(msg.author.id.0)
|
|
{
|
|
None => {
|
|
msg.reply(&ctx.http, "You are not in the game!").await?;
|
|
return Ok(());
|
|
}
|
|
Some(player) => player,
|
|
};
|
|
|
|
if let Some(target_player) = global_data.game_state()?.get_player_by_codename(&target) {
|
|
if src_player.discord_id == target_player.discord_id {
|
|
msg.reply(&ctx.http, "You can't send messages to yourself!")
|
|
.await?;
|
|
return Ok(());
|
|
}
|
|
|
|
let woxlf_msg = WoxlfMessage::default()
|
|
.source(MessageSource::Player(Box::new(src_player.clone())))
|
|
.dest(MessageDest::Player(Box::new(target_player.clone())))
|
|
.median(Median::DirectMessage)
|
|
.content(pm)
|
|
.clone();
|
|
|
|
dispatch_message(ctx, &mut global_data, woxlf_msg).await?;
|
|
} else {
|
|
msg.reply(
|
|
&ctx.http,
|
|
format!("Could not find a player with codename {}.", target),
|
|
)
|
|
.await?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|