Skip to main content

twitch_irc/message/commands/
notice.rs

1use crate::message::commands::IRCMessageParseExt;
2use crate::message::{IRCMessage, ServerMessageParseError};
3use std::convert::TryFrom;
4
5#[cfg(feature = "with-serde")]
6use {serde::Deserialize, serde::Serialize};
7
8/// A user-facing notice sent by the server.
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[cfg_attr(feature = "with-serde", derive(Serialize, Deserialize))]
11pub struct NoticeMessage {
12    /// The login name of the channel that this notice was sent to. There are cases where this
13    /// is missing, for example when a `NOTICE` message is sent in response to a failed login
14    /// attempt.
15    pub channel_login: Option<String>,
16    /// Message content of the notice. This is some user-friendly string, e.g.
17    /// `You are permanently banned from talking in <channel>.`
18    pub message_text: String,
19    /// If present, a computer-readable string identifying the class/type of notice.
20    /// For example `msg_banned`. These message IDs are [documented by Twitch here](https://dev.twitch.tv/docs/irc/msg-id).
21    pub message_id: Option<String>,
22
23    /// The message that this `NoticeMessage` was parsed from.
24    pub source: IRCMessage,
25}
26
27impl TryFrom<IRCMessage> for NoticeMessage {
28    type Error = ServerMessageParseError;
29
30    fn try_from(source: IRCMessage) -> Result<NoticeMessage, ServerMessageParseError> {
31        if source.command != "NOTICE" {
32            return Err(ServerMessageParseError::MismatchedCommand(Box::new(source)));
33        }
34
35        Ok(NoticeMessage {
36            channel_login: source
37                .try_get_optional_channel_login()?
38                .map(|s| s.to_owned()),
39            message_text: source.try_get_param(1)?.to_owned(),
40            message_id: source
41                .try_get_optional_nonempty_tag_value("msg-id")?
42                .map(|s| s.to_owned()),
43            source,
44        })
45    }
46}
47
48impl From<NoticeMessage> for IRCMessage {
49    fn from(msg: NoticeMessage) -> IRCMessage {
50        msg.source
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use crate::message::{IRCMessage, NoticeMessage};
57    use std::convert::TryFrom;
58
59    #[test]
60    pub fn test_basic() {
61        let src = "@msg-id=msg_banned :tmi.twitch.tv NOTICE #forsen :You are permanently banned from talking in forsen.";
62        let irc_message = IRCMessage::parse(src).unwrap();
63        let msg = NoticeMessage::try_from(irc_message.clone()).unwrap();
64
65        assert_eq!(
66            msg,
67            NoticeMessage {
68                channel_login: Some("forsen".to_owned()),
69                message_text: "You are permanently banned from talking in forsen.".to_owned(),
70                message_id: Some("msg_banned".to_owned()),
71                source: irc_message
72            }
73        );
74    }
75
76    #[test]
77    pub fn test_pre_login() {
78        // this style of notice is received before successful login
79        let src = ":tmi.twitch.tv NOTICE * :Improperly formatted auth";
80        let irc_message = IRCMessage::parse(src).unwrap();
81        let msg = NoticeMessage::try_from(irc_message.clone()).unwrap();
82
83        assert_eq!(
84            msg,
85            NoticeMessage {
86                channel_login: None,
87                message_text: "Improperly formatted auth".to_owned(),
88                message_id: None,
89                source: irc_message
90            }
91        );
92    }
93}