fix(channels): preserve slack thread root ids

This commit is contained in:
Chummy 2026-02-19 18:37:08 +08:00
parent 9afe4f28e7
commit e83e017062
2 changed files with 41 additions and 1 deletions

View file

@ -75,6 +75,7 @@ mod tests {
content: "hello".into(), content: "hello".into(),
recipient: "user".into(), recipient: "user".into(),
subject: None, subject: None,
thread_ts: None,
}) })
.await; .await;
assert!(result.is_ok()); assert!(result.is_ok());
@ -88,6 +89,7 @@ mod tests {
content: String::new(), content: String::new(),
recipient: String::new(), recipient: String::new(),
subject: None, subject: None,
thread_ts: None,
}) })
.await; .await;
assert!(result.is_ok()); assert!(result.is_ok());

View file

@ -45,6 +45,15 @@ impl SlackChannel {
.and_then(|u| u.as_str()) .and_then(|u| u.as_str())
.map(String::from) .map(String::from)
} }
/// Resolve the thread identifier for inbound Slack messages.
/// Replies carry `thread_ts` (root thread id); top-level messages only have `ts`.
fn inbound_thread_ts(msg: &serde_json::Value, ts: &str) -> Option<String> {
msg.get("thread_ts")
.and_then(|t| t.as_str())
.or(if ts.is_empty() { None } else { Some(ts) })
.map(str::to_string)
}
} }
#[async_trait] #[async_trait]
@ -174,7 +183,7 @@ impl Channel for SlackChannel {
.duration_since(std::time::UNIX_EPOCH) .duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default() .unwrap_or_default()
.as_secs(), .as_secs(),
thread_ts: Some(ts.to_string()), thread_ts: Self::inbound_thread_ts(msg, ts),
}; };
if tx.send(channel_msg).await.is_err() { if tx.send(channel_msg).await.is_err() {
@ -308,4 +317,33 @@ mod tests {
assert!(!id.contains('-')); // No UUID dashes assert!(!id.contains('-')); // No UUID dashes
assert!(id.starts_with("slack_")); assert!(id.starts_with("slack_"));
} }
#[test]
fn inbound_thread_ts_prefers_explicit_thread_ts() {
let msg = serde_json::json!({
"ts": "123.002",
"thread_ts": "123.001"
});
let thread_ts = SlackChannel::inbound_thread_ts(&msg, "123.002");
assert_eq!(thread_ts.as_deref(), Some("123.001"));
}
#[test]
fn inbound_thread_ts_falls_back_to_ts() {
let msg = serde_json::json!({
"ts": "123.001"
});
let thread_ts = SlackChannel::inbound_thread_ts(&msg, "123.001");
assert_eq!(thread_ts.as_deref(), Some("123.001"));
}
#[test]
fn inbound_thread_ts_none_when_ts_missing() {
let msg = serde_json::json!({});
let thread_ts = SlackChannel::inbound_thread_ts(&msg, "");
assert_eq!(thread_ts, None);
}
} }