use crate::game::listener::{EventStatus, Listener, ListenerContext, Priority}; use crate::game::message_router::{ send_private_message, Median, MessageDest, MessageSource, WoxlfMessage, }; use crate::game::role::Role; use rand::{thread_rng, Rng}; use serenity::async_trait; use serenity::model::prelude::UserId; use serenity::utils::MessageBuilder; #[derive(Debug)] pub struct SpyListener {} #[async_trait] impl Listener for SpyListener { fn get_priority(&self) -> Priority { Priority::Logging } async fn on_chat( &mut self, ctx: &mut ListenerContext, msg: &WoxlfMessage, ) -> crate::error::Result { if msg.median != Median::DirectMessage { return Ok(EventStatus::Okay); } let src_player = if let MessageSource::Player(p) = &msg.source { p } else { return Ok(EventStatus::Okay); }; let dest_player = if let MessageDest::Player(p) = &msg.dest { p } else { return Ok(EventStatus::Okay); }; let spy_player = ctx .data .game_state()? .player_data .iter() .find(|p| p.alive && p.role == Role::Spy); if let Some(spy_player) = spy_player { if spy_player.discord_id == dest_player.discord_id || spy_player.discord_id == src_player.discord_id { return Ok(EventStatus::Okay); } // 1/4 chance to intercept message if thread_rng().gen_bool(0.25) { let msg_content = MessageBuilder::default() .push_bold_line_safe(format!( "{} Sent {} a private message:", src_player.codename, dest_player.codename )) .push(msg.content.clone()) .build(); send_private_message( &ctx.ctx.http, UserId::from(spy_player.discord_id), &msg_content, &None, ) .await? } } return Ok(EventStatus::Okay); } }