atc/libs/
command.rs

1use lazy_static::lazy_static;
2use regex::Regex;
3
4use super::frame::Frame;
5
6lazy_static! {
7    static ref RE_CMD_IDENTIFY: Regex = Regex::new(r"^@identify<(?P<channel_id>[a-zA-Z\d_-]+)>").unwrap();
8    static ref RE_CMD_CHANNEL_MESSAGE: Regex =
9        Regex::new(r"^@message<(?P<channel_id>[a-zA-Z\d_-]+)>(?P<message>.*)$").unwrap();
10    static ref RE_CMD_TERMINATE: Regex = Regex::new(r"^@terminate<(?P<channel_id>[a-zA-Z\d_-]+)>").unwrap();
11}
12
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum ServerCommand {
16    /// Send message to give target.
17    Message(Option<String>, String),
18
19    /// Send identifier
20    Identify(String),
21
22    /// Terminate server.
23    Terminate,
24}
25
26#[derive(Debug, Clone)]
27pub enum ChannelCommand {
28    /// Identify the connection endpoint, normally use `channel-id`.
29    Identify(String),
30
31    /// Terminate connection.
32    Terminate(String),
33
34    /// Channel message. normally sent by server.
35    ChannelMessage((String, String)),
36
37    /// Ping msg
38    Ping,
39
40    /// Pong msg
41    Pong,
42}
43
44impl Into<Frame> for ChannelCommand {
45    fn into(self) -> Frame {
46        (match self {
47            ChannelCommand::Identify(id) => format!("@identify<{}>", id),
48            ChannelCommand::Terminate(id) => format!("@terminate<{}>", id),
49            ChannelCommand::ChannelMessage((id, msg)) => {
50                format!("@message<{}>{}", id, msg)
51            }
52            ChannelCommand::Ping => format!("@ping"),
53            ChannelCommand::Pong => format!("@pong"),
54        })
55        .into()
56    }
57}
58
59impl From<Frame> for ChannelCommand {
60    fn from(value: Frame) -> Self {
61        let value: String = value.into();
62        if &value == "@ping" {
63            return Self::Ping;
64        } else if &value == "@pong" {
65            return Self::Pong;
66        }
67
68        if RE_CMD_IDENTIFY.is_match(&value) {
69            if let Some(cap) = RE_CMD_IDENTIFY.captures(&value) {
70                if let Some(mat) = cap.name("channel_id") {
71                    return Self::Identify(mat.as_str().to_string());
72                }
73            }
74        } else if RE_CMD_TERMINATE.is_match(&value) {
75            if let Some(cap) = RE_CMD_TERMINATE.captures(&value) {
76                if let Some(mat) = cap.name("channel_id") {
77                    return Self::Terminate(mat.as_str().to_string());
78                }
79            }
80        } else if RE_CMD_CHANNEL_MESSAGE.is_match(&value) {
81            if let Some(cap) = RE_CMD_CHANNEL_MESSAGE.captures(&value) {
82                if let Some(mat_id) = cap.name("channel_id") {
83                    if let Some(mat_msg) = cap.name("message") {
84                        return Self::ChannelMessage((
85                            mat_id.as_str().to_string(),
86                            mat_msg.as_str().to_string(),
87                        ));
88                    }
89                    return Self::ChannelMessage((mat_id.as_str().to_string(), String::new()));
90                }
91            }
92        }
93        panic!("Unknown AiTcpCommand input: `{}`", value);
94    }
95}