diff --git a/src/base.rs b/src/base.rs index 05f2ce6..3a3d1e7 100644 --- a/src/base.rs +++ b/src/base.rs @@ -152,7 +152,11 @@ pub enum MessageAction { Edit, /// React to a message with an Emoji. - React(String), + /// + /// `:react` will by default try to convert the [String] argument to an Emoji, and error when + /// it doesn't recognize it. The second [bool] argument forces it to be interpreted literally + /// when it is `true`. + React(String, bool), /// Redact a message, with an optional reason. /// @@ -166,7 +170,11 @@ pub enum MessageAction { /// /// If no specific Emoji to remove to is specified, then all reactions from the user on the /// message are removed. - Unreact(Option), + /// + /// Like `:react`, `:unreact` will by default try to convert the [String] argument to an Emoji, + /// and error when it doesn't recognize it. The second [bool] argument forces it to be + /// interpreted literally when it is `true`. + Unreact(Option, bool), } /// The type of room being created. diff --git a/src/commands.rs b/src/commands.rs index f8b3515..c287756 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -221,24 +221,17 @@ fn iamb_edit(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult { } fn iamb_react(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult { - let args = desc.arg.strings()?; + let mut args = desc.arg.strings()?; if args.len() != 1 { return Result::Err(CommandError::InvalidArgument); } - let k = args[0].as_str(); - - if let Some(emoji) = emojis::get(k).or_else(|| emojis::get_by_shortcode(k)) { - let mact = IambAction::from(MessageAction::React(emoji.to_string())); - let step = CommandStep::Continue(mact.into(), ctx.context.clone()); - - return Ok(step); - } else { - let msg = format!("Invalid Emoji or shortcode: {k}"); + let react = args.remove(0); + let mact = IambAction::from(MessageAction::React(react, desc.bang)); + let step = CommandStep::Continue(mact.into(), ctx.context.clone()); - return Result::Err(CommandError::Error(msg)); - } + return Ok(step); } fn iamb_unreact(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult { @@ -248,20 +241,8 @@ fn iamb_unreact(desc: CommandDescription, ctx: &mut ProgContext) -> ProgResult { return Result::Err(CommandError::InvalidArgument); } - let mact = if let Some(k) = args.pop() { - let k = k.as_str(); - - if let Some(emoji) = emojis::get(k).or_else(|| emojis::get_by_shortcode(k)) { - IambAction::from(MessageAction::Unreact(Some(emoji.to_string()))) - } else { - let msg = format!("Invalid Emoji or shortcode: {k}"); - - return Result::Err(CommandError::Error(msg)); - } - } else { - IambAction::from(MessageAction::Unreact(None)) - }; - + let reaction = args.pop(); + let mact = IambAction::from(MessageAction::Unreact(reaction, desc.bang)); let step = CommandStep::Continue(mact.into(), ctx.context.clone()); return Ok(step); diff --git a/src/windows/room/chat.rs b/src/windows/room/chat.rs index 31b4f88..427a2df 100644 --- a/src/windows/room/chat.rs +++ b/src/windows/room/chat.rs @@ -358,7 +358,22 @@ impl ChatState { Ok(None) }, - MessageAction::React(emoji) => { + MessageAction::React(reaction, literal) => { + let emoji = if literal { + reaction + } else if let Some(emoji) = + emojis::get(&reaction).or_else(|| emojis::get_by_shortcode(&reaction)) + { + emoji.to_string() + } else { + let msg = format!("{reaction:?} is not a known Emoji shortcode; do you want to react with exactly {reaction:?}?"); + let act = IambAction::Message(MessageAction::React(reaction, true)); + let prompt = PromptYesNo::new(msg, vec![Action::from(act)]); + let prompt = Box::new(prompt); + + return Err(UIError::NeedConfirm(prompt)); + }; + let room = self.get_joined(&store.application.worker)?; let event_id = match &msg.event { MessageEvent::EncryptedOriginal(ev) => ev.event_id.clone(), @@ -422,7 +437,27 @@ impl ChatState { Ok(None) }, - MessageAction::Unreact(emoji) => { + MessageAction::Unreact(reaction, literal) => { + let emoji = match reaction { + reaction if literal => reaction, + Some(reaction) => { + if let Some(emoji) = + emojis::get(&reaction).or_else(|| emojis::get_by_shortcode(&reaction)) + { + Some(emoji.to_string()) + } else { + let msg = format!("{reaction:?} is not a known Emoji shortcode; do you want to remove exactly {reaction:?}?"); + let act = + IambAction::Message(MessageAction::Unreact(Some(reaction), true)); + let prompt = PromptYesNo::new(msg, vec![Action::from(act)]); + let prompt = Box::new(prompt); + + return Err(UIError::NeedConfirm(prompt)); + } + }, + None => None, + }; + let room = self.get_joined(&store.application.worker)?; let event_id = match &msg.event { MessageEvent::EncryptedOriginal(ev) => ev.event_id.clone(),