From 3462de1eee5832d3a3bc2863a95c4f62cc6c2e03 Mon Sep 17 00:00:00 2001 From: Edison Jwa Date: Tue, 9 Jun 2026 01:44:03 +0900 Subject: [PATCH] fix(core): allow empty poke dispatch --- core/chanora_core/src/lib.rs | 38 +++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/core/chanora_core/src/lib.rs b/core/chanora_core/src/lib.rs index 77ed1fc..883aaf6 100644 --- a/core/chanora_core/src/lib.rs +++ b/core/chanora_core/src/lib.rs @@ -174,6 +174,10 @@ fn normalize_channel_password(password: Option) -> Option { .filter(|p| !p.is_empty()) } +fn should_dispatch_text_message(message: &str, target: &MessageTarget) -> bool { + !message.trim().is_empty() || matches!(target, MessageTarget::Poke(_)) +} + /// The top-level Chanora session. Owns at most one active server /// connection (DEC-006). #[derive(Clone)] @@ -673,7 +677,7 @@ impl ChanoraSession { message: String, target: MessageTarget, ) -> Result<(), CoreError> { - if message.trim().is_empty() { + if !should_dispatch_text_message(&message, &target) { return Ok(()); } let guard = self.inner.lock().await; @@ -2535,6 +2539,38 @@ mod tests { ); } + #[test] + fn empty_poke_messages_are_dispatchable() { + assert!(super::should_dispatch_text_message( + "", + &MessageTarget::Poke(42) + )); + assert!(super::should_dispatch_text_message( + " \t ", + &MessageTarget::Poke(42) + )); + } + + #[test] + fn empty_non_poke_messages_remain_suppressed() { + assert!(!super::should_dispatch_text_message( + "", + &MessageTarget::Server + )); + assert!(!super::should_dispatch_text_message( + " ", + &MessageTarget::Channel + )); + assert!(!super::should_dispatch_text_message( + "", + &MessageTarget::Client(42) + )); + assert!(super::should_dispatch_text_message( + "hello", + &MessageTarget::Channel + )); + } + #[tokio::test] async fn empty_address_is_rejected() { let s = ChanoraSession::new();