Skip to main content

openlark_webhook/
models.rs

1//! 消息类型和内容结构定义
2
3use serde::{Deserialize, Serialize};
4
5/// 消息类型枚举
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "snake_case")]
8pub enum MsgType {
9    /// 文本消息
10    Text,
11    /// 富文本消息
12    Post,
13    /// 图片消息
14    Image,
15    /// 文件消息
16    File,
17    /// 卡片消息(交互式)
18    #[cfg(feature = "card")]
19    Interactive,
20}
21
22/// 文本消息内容
23#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct TextContent {
25    /// 消息文本
26    pub text: String,
27}
28
29impl TextContent {
30    /// 创建文本消息内容。
31    pub fn new(text: String) -> Self {
32        Self { text }
33    }
34}
35
36/// 富文本消息内容
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct PostContent {
39    /// 富文本 JSON 字符串
40    pub post: String,
41}
42
43impl PostContent {
44    /// 创建富文本消息内容。
45    pub fn new(post: String) -> Self {
46        Self { post }
47    }
48}
49
50/// 图片消息内容
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct ImageContent {
53    /// 图片 key
54    pub image_key: String,
55}
56
57impl ImageContent {
58    /// 创建图片消息内容。
59    pub fn new(image_key: String) -> Self {
60        Self { image_key }
61    }
62}
63
64/// 文件消息内容
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct FileContent {
67    /// 文件 key
68    pub file_key: String,
69}
70
71impl FileContent {
72    /// 创建文件消息内容。
73    pub fn new(file_key: String) -> Self {
74        Self { file_key }
75    }
76}
77
78/// 卡片消息内容(交互式)
79#[cfg(feature = "card")]
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct InteractiveContent {
82    /// 卡片 JSON 对象
83    pub card: serde_json::Value,
84}
85
86#[cfg(feature = "card")]
87impl InteractiveContent {
88    /// 创建交互式卡片消息内容。
89    pub fn new(card: serde_json::Value) -> Self {
90        Self { card }
91    }
92}
93
94#[cfg(test)]
95#[allow(unused_imports)]
96mod tests {
97    use super::*;
98
99    #[test]
100    fn test_text_content_serialization() {
101        let content = TextContent::new("Hello, World!".to_string());
102        let json = serde_json::to_value(&content).unwrap();
103        assert_eq!(json["text"], "Hello, World!");
104    }
105
106    #[test]
107    fn test_post_content_serialization() {
108        let post_json = r#"{"title":"Test","content":"Content"}"#.to_string();
109        let content = PostContent::new(post_json.clone());
110        let json = serde_json::to_value(&content).unwrap();
111        assert_eq!(json["post"], post_json);
112    }
113
114    #[test]
115    fn test_image_content_serialization() {
116        let content = ImageContent::new("img_abc123".to_string());
117        let json = serde_json::to_value(&content).unwrap();
118        assert_eq!(json["image_key"], "img_abc123");
119    }
120
121    #[test]
122    fn test_file_content_serialization() {
123        let content = FileContent::new("file_xyz789".to_string());
124        let json = serde_json::to_value(&content).unwrap();
125        assert_eq!(json["file_key"], "file_xyz789");
126    }
127
128    #[test]
129    fn test_msg_type_serialization() {
130        let text_type = MsgType::Text;
131        let json = serde_json::to_value(text_type).unwrap();
132        assert_eq!(json, "text");
133
134        let image_type = MsgType::Image;
135        let json = serde_json::to_value(image_type).unwrap();
136        assert_eq!(json, "image");
137    }
138
139    #[cfg(feature = "card")]
140    #[test]
141    fn test_interactive_content_serialization() {
142        let card_json = serde_json::json!({
143            "type": "template",
144            "data": {
145                "template_id": "test_template"
146            }
147        });
148        let content = InteractiveContent::new(card_json.clone());
149        let json = serde_json::to_value(&content).unwrap();
150        assert_eq!(json["card"], card_json);
151    }
152
153    #[cfg(feature = "card")]
154    #[test]
155    fn test_msg_type_interactive_serialization() {
156        let interactive_type = MsgType::Interactive;
157        let json = serde_json::to_value(interactive_type).unwrap();
158        assert_eq!(json, "interactive");
159    }
160}