twitch_irc/message/commands/
clearchat.rs1use crate::message::commands::IRCMessageParseExt;
2use crate::message::{IRCMessage, ServerMessageParseError};
3use chrono::{DateTime, Utc};
4use std::convert::TryFrom;
5use std::str::FromStr;
6use std::time::Duration;
7
8#[cfg(feature = "with-serde")]
9use {serde::Deserialize, serde::Serialize};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
15#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
16pub struct ClearChatMessage {
17 pub channel_login: String,
19 pub channel_id: String,
21 pub action: ClearChatAction,
24 pub server_timestamp: DateTime<Utc>,
26
27 pub source: IRCMessage,
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
33#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
34pub enum ClearChatAction {
35 ChatCleared,
37 UserBanned {
39 user_login: String,
41 user_id: String,
43 },
44 UserTimedOut {
46 user_login: String,
48 user_id: String,
50 timeout_length: Duration,
52 },
53}
54
55impl TryFrom<IRCMessage> for ClearChatMessage {
56 type Error = ServerMessageParseError;
57
58 fn try_from(source: IRCMessage) -> Result<ClearChatMessage, ServerMessageParseError> {
59 if source.command != "CLEARCHAT" {
60 return Err(ServerMessageParseError::MismatchedCommand(Box::new(source)));
61 }
62
63 let action = match source.params.get(1) {
71 Some(user_login) => {
72 let user_id = source.try_get_nonempty_tag_value("target-user-id")?;
74
75 let ban_duration = source.try_get_optional_nonempty_tag_value("ban-duration")?;
76 match ban_duration {
77 Some(ban_duration) => {
78 let ban_duration = u64::from_str(ban_duration).map_err(|_| {
79 ServerMessageParseError::MalformedTagValue(
80 Box::new(source.clone()),
81 "ban-duration",
82 ban_duration.to_owned(),
83 )
84 })?;
85
86 ClearChatAction::UserTimedOut {
87 user_login: user_login.to_owned(),
88 user_id: user_id.to_owned(),
89 timeout_length: Duration::from_secs(ban_duration),
90 }
91 }
92 None => ClearChatAction::UserBanned {
93 user_login: user_login.to_owned(),
94 user_id: user_id.to_owned(),
95 },
96 }
97 }
98 None => ClearChatAction::ChatCleared,
99 };
100
101 Ok(ClearChatMessage {
102 channel_login: source.try_get_channel_login()?.to_owned(),
103 channel_id: source.try_get_nonempty_tag_value("room-id")?.to_owned(),
104 action,
105 server_timestamp: source.try_get_timestamp("tmi-sent-ts")?,
106 source,
107 })
108 }
109}
110
111impl From<ClearChatMessage> for IRCMessage {
112 fn from(msg: ClearChatMessage) -> IRCMessage {
113 msg.source
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use crate::message::commands::clearchat::ClearChatAction;
120 use crate::message::{ClearChatMessage, IRCMessage};
121 use chrono::{TimeZone, Utc};
122 use std::convert::TryFrom;
123 use std::time::Duration;
124
125 #[test]
126 pub fn test_timeout() {
127 let src = "@ban-duration=1;room-id=11148817;target-user-id=148973258;tmi-sent-ts=1594553828245 :tmi.twitch.tv CLEARCHAT #pajlada :fabzeef";
128 let irc_message = IRCMessage::parse(src).unwrap();
129 let msg = ClearChatMessage::try_from(irc_message.clone()).unwrap();
130
131 assert_eq!(
132 msg,
133 ClearChatMessage {
134 channel_login: "pajlada".to_owned(),
135 channel_id: "11148817".to_owned(),
136 action: ClearChatAction::UserTimedOut {
137 user_login: "fabzeef".to_owned(),
138 user_id: "148973258".to_owned(),
139 timeout_length: Duration::from_secs(1)
140 },
141 server_timestamp: Utc.timestamp_millis_opt(1_594_553_828_245).unwrap(),
142 source: irc_message
143 }
144 );
145 }
146
147 #[test]
148 pub fn test_permaban() {
149 let src = "@room-id=11148817;target-user-id=70948394;tmi-sent-ts=1594561360331 :tmi.twitch.tv CLEARCHAT #pajlada :weeb123";
150 let irc_message = IRCMessage::parse(src).unwrap();
151 let msg = ClearChatMessage::try_from(irc_message.clone()).unwrap();
152
153 assert_eq!(
154 msg,
155 ClearChatMessage {
156 channel_login: "pajlada".to_owned(),
157 channel_id: "11148817".to_owned(),
158 action: ClearChatAction::UserBanned {
159 user_login: "weeb123".to_owned(),
160 user_id: "70948394".to_owned(),
161 },
162 server_timestamp: Utc.timestamp_millis_opt(1_594_561_360_331).unwrap(),
163 source: irc_message
164 }
165 );
166 }
167
168 #[test]
169 pub fn test_chat_clear() {
170 let src = "@room-id=40286300;tmi-sent-ts=1594561392337 :tmi.twitch.tv CLEARCHAT #randers";
171 let irc_message = IRCMessage::parse(src).unwrap();
172 let msg = ClearChatMessage::try_from(irc_message.clone()).unwrap();
173
174 assert_eq!(
175 msg,
176 ClearChatMessage {
177 channel_login: "randers".to_owned(),
178 channel_id: "40286300".to_owned(),
179 action: ClearChatAction::ChatCleared,
180 server_timestamp: Utc.timestamp_millis_opt(1_594_561_392_337).unwrap(),
181 source: irc_message
182 }
183 );
184 }
185}