Skip to content

Commit d5ebe5c

Browse files
committed
feat: introduce Markdown conversion for Slack and Lark adapters, improving message formatting.
1 parent 83108fe commit d5ebe5c

File tree

8 files changed

+325
-7
lines changed

8 files changed

+325
-7
lines changed

Cargo.lock

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ This project is currently **work in progress**. Core routing is being built; the
99
- Normalizes content to Markdown with minimal metadata.
1010
- Forwards to one or more downstream webhook targets.
1111

12+
## Markdown Compatibility
13+
The system ensures your messages look great on any platform by automatically converting standard Markdown:
14+
- **Slack**: Converts standard Markdown (e.g., `**bold**`, `[link](url)`) to Slack's native `mrkdwn` syntax.
15+
- **Lark / Feishu**: Transforms Markdown into Lark's JSON "Post" (Rich Text) format to support native styling.
16+
- **WeCom / DingTalk**: Optimizes formatting for their respective Markdown subsets.
17+
1218
## Status
1319
- Backend routing: in active development.
1420
- Console UI: in progress.

apps/webhook_router/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ uuid = { version = "1", features = ["v4", "serde"] }
2020
markdown = "1.0.0"
2121
utoipa = { version = "5", features = ["axum_extras"] }
2222
utoipa-swagger-ui = { version = "8", features = ["axum"] }
23+
pulldown-cmark = "0.13.0"
2324

2425

2526
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

apps/webhook_router/src/adapters/lark.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use uuid::Uuid;
33

44
use crate::adapters::{AdapterError, WebhookAdapter};
55
use crate::models::{OutgoingPayload, UemEvent};
6+
use crate::utils::markdown::LarkConverter;
67

78
#[derive(Debug)]
89
pub struct LarkAdapter;
@@ -57,10 +58,11 @@ impl WebhookAdapter for LarkAdapter {
5758
}
5859

5960
fn uem_to_egress(&self, event: &UemEvent) -> Result<OutgoingPayload, AdapterError> {
61+
let post_content = LarkConverter::convert(&event.markdown);
6062
Ok(OutgoingPayload {
6163
body: json!({
62-
"msg_type": "text",
63-
"content": { "text": event.markdown }
64+
"msg_type": "post",
65+
"content": { "post": post_content }
6466
}),
6567
content_type: "application/json",
6668
})
@@ -116,7 +118,10 @@ mod tests {
116118
meta: json!({}),
117119
};
118120
let payload = adapter.uem_to_egress(&event).expect("payload");
119-
assert_eq!(payload.body["msg_type"], "text");
120-
assert_eq!(payload.body["content"]["text"], "hello");
121+
assert_eq!(payload.body["msg_type"], "post");
122+
// Verify post content structure exists
123+
assert!(payload.body["content"]["post"]["zh_cn"]["content"].is_array());
124+
let content_text = &payload.body["content"]["post"]["zh_cn"]["content"][0][0]["text"];
125+
assert_eq!(content_text, "hello");
121126
}
122127
}

apps/webhook_router/src/adapters/slack.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use uuid::Uuid;
33

44
use crate::adapters::{AdapterError, WebhookAdapter};
55
use crate::models::{OutgoingPayload, UemEvent};
6+
use crate::utils::markdown::SlackConverter;
67

78
#[derive(Debug)]
89
pub struct SlackAdapter;
@@ -48,8 +49,9 @@ impl WebhookAdapter for SlackAdapter {
4849
}
4950

5051
fn uem_to_egress(&self, event: &UemEvent) -> Result<OutgoingPayload, AdapterError> {
52+
let mrkdwn = SlackConverter::convert(&event.markdown);
5153
Ok(OutgoingPayload {
52-
body: json!({ "text": event.markdown }),
54+
body: json!({ "text": mrkdwn }),
5355
content_type: "application/json",
5456
})
5557
}
@@ -95,11 +97,11 @@ mod tests {
9597
source: "slack".to_string(),
9698
timestamp: 1,
9799
title: None,
98-
markdown: "hello".to_string(),
100+
markdown: "**bold**".to_string(),
99101
raw: json!({}),
100102
meta: json!({}),
101103
};
102104
let payload = adapter.uem_to_egress(&event).expect("payload");
103-
assert_eq!(payload.body["text"], "hello");
105+
assert_eq!(payload.body["text"], "*bold*");
104106
}
105107
}

apps/webhook_router/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod adapters;
1010
mod db;
1111
mod handlers;
1212
mod models;
13+
mod utils;
1314

1415
use handlers::{api_router, basic_auth, healthz, ingress, AppState, ApiDoc};
1516
use models::BasicAuth;

0 commit comments

Comments
 (0)