twitch_irc/message/commands/
userstate.rs1use crate::message::commands::IRCMessageParseExt;
2use crate::message::twitch::{Badge, RGBColor};
3use crate::message::{IRCMessage, ServerMessageParseError};
4use std::collections::HashSet;
5use std::convert::TryFrom;
6
7#[cfg(feature = "with-serde")]
8use {serde::Deserialize, serde::Serialize};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
18pub struct UserStateMessage {
19 pub channel_login: String,
21 pub user_name: String,
23 pub badge_info: Vec<Badge>,
30 pub badges: Vec<Badge>,
32 pub emote_sets: HashSet<String>,
34 pub name_color: Option<RGBColor>,
36
37 pub source: IRCMessage,
39}
40
41impl TryFrom<IRCMessage> for UserStateMessage {
42 type Error = ServerMessageParseError;
43
44 fn try_from(source: IRCMessage) -> Result<UserStateMessage, ServerMessageParseError> {
45 if source.command != "USERSTATE" {
46 return Err(ServerMessageParseError::MismatchedCommand(source));
47 }
48
49 Ok(UserStateMessage {
50 channel_login: source.try_get_channel_login()?.to_owned(),
51 user_name: source
52 .try_get_nonempty_tag_value("display-name")?
53 .to_owned(),
54 badge_info: source.try_get_badges("badge-info")?,
55 badges: source.try_get_badges("badges")?,
56 emote_sets: source.try_get_emote_sets("emote-sets")?,
57 name_color: source.try_get_color("color")?,
58 source,
59 })
60 }
61}
62
63impl From<UserStateMessage> for IRCMessage {
64 fn from(msg: UserStateMessage) -> IRCMessage {
65 msg.source
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use crate::message::commands::userstate::UserStateMessage;
72 use crate::message::twitch::RGBColor;
73 use crate::message::{Badge, IRCMessage};
74 use std::convert::TryFrom;
75
76 #[test]
77 pub fn test_basic() {
78 let src = "@badge-info=;badges=;color=#FF0000;display-name=TESTUSER;emote-sets=0;mod=0;subscriber=0;user-type= :tmi.twitch.tv USERSTATE #randers";
79 let irc_message = IRCMessage::parse(src).unwrap();
80 let msg = UserStateMessage::try_from(irc_message.clone()).unwrap();
81
82 assert_eq!(
83 msg,
84 UserStateMessage {
85 channel_login: "randers".to_owned(),
86 user_name: "TESTUSER".to_owned(),
87 badge_info: vec![],
88 badges: vec![],
89 emote_sets: vec!["0".to_owned()].into_iter().collect(),
90 name_color: Some(RGBColor {
91 r: 0xFF,
92 g: 0x00,
93 b: 0x00
94 }),
95 source: irc_message
96 }
97 )
98 }
99
100 #[test]
101 pub fn test_uuid_emote_set_id() {
102 let src = "@badge-info=;badges=moderator/1;color=#8A2BE2;display-name=TESTUSER;emote-sets=0,75c09c7b-332a-43ec-8be8-1d4571706155;mod=1;subscriber=0;user-type=mod :tmi.twitch.tv USERSTATE #randers";
103 let irc_message = IRCMessage::parse(src).unwrap();
104 let msg = UserStateMessage::try_from(irc_message.clone()).unwrap();
105
106 assert_eq!(
107 msg,
108 UserStateMessage {
109 channel_login: "randers".to_owned(),
110 user_name: "TESTUSER".to_owned(),
111 badge_info: vec![],
112 badges: vec![Badge {
113 name: "moderator".to_owned(),
114 version: "1".to_owned()
115 }],
116 emote_sets: vec![
117 "0".to_owned(),
118 "75c09c7b-332a-43ec-8be8-1d4571706155".to_owned()
119 ]
120 .into_iter()
121 .collect(),
122 name_color: Some(RGBColor {
123 r: 0x8A,
124 g: 0x2B,
125 b: 0xE2
126 }),
127 source: irc_message
128 }
129 )
130 }
131}