1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Behaviors {
    OpenUrl(OpenUrlBehavior),
    Callback(CallbackBehavior),
    Form(FormBehavior),
}

/// 跳转链接交互
#[derive(Debug, Serialize, Deserialize)]
pub struct OpenUrlBehavior {
    /// 声明交互类型。要配置跳转链接交互,取固定值 open_url。
    r#type: String,
    /// 兜底跳转地址。
    default_url: String,
    /// Android 端的链接地址。可配置为 lark://msgcard/unsupported_action 声明当前端不允许跳转。
    #[serde(skip_serializing_if = "Option::is_none")]
    android_url: Option<String>,
    /// iOS 端的链接地址。可配置为 lark://msgcard/unsupported_action 声明当前端不允许跳转。
    #[serde(skip_serializing_if = "Option::is_none")]
    ios_url: Option<String>,
    /// PC 端的链接地址。可配置为 lark://msgcard/unsupported_action 声明当前端不允许跳转。
    #[serde(skip_serializing_if = "Option::is_none")]
    pc_url: Option<String>,
}

impl OpenUrlBehavior {
    pub fn new(default_url: &str) -> Self {
        Self {
            r#type: "open_url".to_string(),
            default_url: default_url.to_string(),
            android_url: None,
            ios_url: None,
            pc_url: None,
        }
    }

    pub fn default_url(mut self, url: &str) -> Self {
        self.default_url = url.to_string();
        self
    }

    pub fn android_url(mut self, url: &str) -> Self {
        self.android_url = Some(url.to_string());
        self
    }

    pub fn ios_url(mut self, url: &str) -> Self {
        self.ios_url = Some(url.to_string());
        self
    }

    pub fn pc_url(mut self, url: &str) -> Self {
        self.pc_url = Some(url.to_string());
        self
    }
}

/// 服务端回传交互
#[derive(Debug, Serialize, Deserialize)]
pub struct CallbackBehavior {
    r#type: String,
    value: Value,
}

impl CallbackBehavior {
    pub fn new(value: Value) -> Self {
        Self {
            r#type: "callback".to_string(),
            value,
        }
    }
}

/// 表单事件交互
#[derive(Debug, Serialize, Deserialize)]
pub struct FormBehavior {
    /// 声明交互类型。要配置表单事件交互,取固定值 form_action。
    r#type: String,
    /// 表单事件类型。可取值:
    ///
    /// - submit:提交整个表单
    /// - reset:重置整个表单
    #[serde(skip_serializing_if = "Option::is_none")]
    behavior: Option<String>,
}

impl Default for FormBehavior {
    fn default() -> Self {
        Self {
            r#type: "form_action".to_string(),
            behavior: None,
        }
    }
}

impl FormBehavior {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn behavior(mut self, behavior: &str) -> Self {
        self.behavior = Some(behavior.to_string());
        self
    }
}

#[cfg(test)]
mod test {
    use serde_json::json;

    use crate::card::interactions::{Behaviors, CallbackBehavior, FormBehavior, OpenUrlBehavior};

    #[test]
    fn test_open_url() {
        let jump_behavior = Behaviors::OpenUrl(OpenUrlBehavior::new("xxx"));
        let json = json!({
            "type": "open_url",
            "default_url": "xxx",
        });

        assert_eq!(serde_json::to_value(&jump_behavior).unwrap(), json)
    }

    #[test]
    fn test_callback() {
        let callback_behavior = Behaviors::Callback(CallbackBehavior::new(json!("hello")));
        let json = json!({
            "type": "callback",
            "value": "hello"
        });

        assert_eq!(serde_json::to_value(&callback_behavior).unwrap(), json)
    }

    #[test]
    fn test_form() {
        let form_behavior = Behaviors::Form(FormBehavior::new());
        let json = json!({
           "type": "form_action",
        });

        assert_eq!(serde_json::to_value(&form_behavior).unwrap(), json)
    }
}