dingtalk_stream/messages/
card_callback.rs1use serde::{Deserialize, Serialize};
4
5pub const CARD_CALLBACK_ROUTER_TOPIC: &str = "/v1.0/card/instances/callback";
7
8#[derive(Debug, Clone, Default, Serialize, Deserialize)]
10pub struct CardCallbackMessage {
11 #[serde(default)]
13 pub extension: serde_json::Value,
14 #[serde(rename = "corpId", default)]
16 pub corp_id: String,
17 #[serde(rename = "userId", default)]
19 pub user_id: String,
20 #[serde(rename = "outTrackId", default)]
22 pub card_instance_id: String,
23 #[serde(default)]
25 pub content: serde_json::Value,
26 #[serde(rename = "type", default)]
28 pub callback_type: String,
29 #[serde(rename = "spaceType", default)]
31 pub space_type: String,
32 #[serde(rename = "userIdType", default)]
34 pub user_id_type: i32,
35 #[serde(rename = "spaceId", default)]
37 pub space_id: String,
38}
39
40impl CardCallbackMessage {
41 pub fn from_json_str(data: &str) -> crate::Result<Self> {
43 let raw: serde_json::Value = serde_json::from_str(data)?;
44 Self::from_value(&raw)
45 }
46
47 pub fn from_value(value: &serde_json::Value) -> crate::Result<Self> {
49 let mut msg: Self = serde_json::from_value(value.clone())?;
50
51 if let Some(ext_str) = value.get("extension").and_then(|v| v.as_str()) {
53 if let Ok(parsed) = serde_json::from_str(ext_str) {
54 msg.extension = parsed;
55 }
56 }
57 if let Some(content_str) = value.get("content").and_then(|v| v.as_str()) {
58 if let Ok(parsed) = serde_json::from_str(content_str) {
59 msg.content = parsed;
60 }
61 }
62
63 Ok(msg)
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn test_card_callback_message_from_value() {
73 let json = serde_json::json!({
74 "extension": "{\"key\":\"value\"}",
75 "corpId": "corp_001",
76 "userId": "user_001",
77 "outTrackId": "card_001",
78 "content": "{\"action\":\"click\"}",
79 "type": "actionCallback",
80 "spaceType": "IM_GROUP",
81 "userIdType": 1,
82 "spaceId": "space_001"
83 });
84 let msg = CardCallbackMessage::from_value(&json).unwrap();
85 assert_eq!(msg.corp_id, "corp_001");
86 assert_eq!(msg.user_id, "user_001");
87 assert_eq!(msg.card_instance_id, "card_001");
88 assert_eq!(msg.callback_type, "actionCallback");
89 assert_eq!(msg.space_type, "IM_GROUP");
90 assert_eq!(msg.user_id_type, 1);
91 assert_eq!(msg.extension["key"], "value");
92 assert_eq!(msg.content["action"], "click");
93 }
94
95 #[test]
96 fn test_card_callback_router_topic() {
97 assert_eq!(CARD_CALLBACK_ROUTER_TOPIC, "/v1.0/card/instances/callback");
98 }
99}