use super::{VerbContext, UserVerb, UserVerbRef, UResult, UserError, user_error, get_player_item_or_fail, is_likely_explicit}; use crate::{ models::item::{Item, ItemFlag}, services::broadcast_to_room, }; use mockall_double::double; #[double] use crate::db::DBTrans; use async_trait::async_trait; use ansi::{ignore_special_characters, ansi}; pub async fn say_to_room<'l>( trans: &DBTrans, from_item: &Item, location: &str, say_what: &str, is_explicit: bool ) -> UResult<()> { let (loc_type, loc_code) = location.split_once("/") .ok_or_else(|| UserError("Invalid location".to_owned()))?; let room_item = trans.find_item_by_type_code(loc_type, loc_code).await? .ok_or_else(|| UserError("Room missing".to_owned()))?; if room_item.flags.contains(&ItemFlag::NoSay) { user_error("Your wristpad vibrates and flashes up an error - apparently it has \ been programmed to block your voice from working here.".to_owned())? } let msg_exp = format!( ansi!("{} says: \"{}\"\n"), from_item.display_for_sentence(true, 1, true), say_what ); let msg_lessexp = format!( ansi!("{} says: \"{}\"\n"), from_item.display_for_sentence(false, 1, true), say_what ); broadcast_to_room( trans, location, Some(from_item), &msg_exp, if is_explicit { None } else { Some(&msg_lessexp) } ).await?; Ok(()) } pub struct Verb; #[async_trait] impl UserVerb for Verb { async fn handle(self: &Self, ctx: &mut VerbContext, _verb: &str, remaining: &str) -> UResult<()> { let say_what = ignore_special_characters(remaining); if say_what == "" { user_error("You need to provide a message to send.".to_owned())?; } let player_item = get_player_item_or_fail(ctx).await?; if player_item.is_dead { user_error("Shush, the dead can't talk!".to_string())?; } say_to_room(ctx.trans, &player_item, &player_item.location, &say_what, is_likely_explicit(&say_what)).await } } static VERB_INT: Verb = Verb; pub static VERB: UserVerbRef = &VERB_INT as UserVerbRef;