twilight_http/request/channel/reaction/
mod.rs

1pub(crate) mod delete_reaction;
2
3mod create_reaction;
4mod delete_all_reaction;
5mod delete_all_reactions;
6mod get_reactions;
7
8pub use self::{
9    create_reaction::CreateReaction, delete_all_reaction::DeleteAllReaction,
10    delete_all_reactions::DeleteAllReactions, delete_reaction::DeleteReaction,
11    get_reactions::GetReactions,
12};
13use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
14use std::fmt::{Display, Formatter, Result as FmtResult};
15use twilight_model::id::{marker::EmojiMarker, Id};
16
17/// Handle a reaction of either a custom or unicode emoji.
18#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
19pub enum RequestReactionType<'a> {
20    /// Reaction of a custom emoji.
21    Custom {
22        /// ID of the custom emoji.
23        id: Id<EmojiMarker>,
24        /// Name of the custom emoji.
25        ///
26        /// This is not strictly required, but may be helpful for Discord to
27        /// work with.
28        name: Option<&'a str>,
29    },
30    /// Reaction of a unicode emoji, such as "🌈".
31    Unicode {
32        /// Unicode emoji.
33        name: &'a str,
34    },
35}
36
37/// Format a [`RequestReactionType`] into a format acceptable for use in URLs.
38///
39/// # Examples
40///
41/// Format a custom reaction for use in a URL:
42///
43/// ```
44/// use twilight_http::request::channel::reaction::RequestReactionType;
45/// use twilight_model::id::Id;
46///
47/// let reaction = RequestReactionType::Custom {
48///     id: Id::new(123),
49///     name: Some("rarity"),
50/// };
51///
52/// assert_eq!("rarity:123", reaction.to_string());
53/// ```
54///
55/// Format the transgeneder flag for use in a URL:
56///
57/// ```
58/// use twilight_http::request::channel::reaction::RequestReactionType;
59///
60/// let reaction = RequestReactionType::Unicode {
61///     name: "🏳️‍⚧️"
62/// };
63///
64/// assert_eq!(
65///     "%F0%9F%8F%B3%EF%B8%8F%E2%80%8D%E2%9A%A7%EF%B8%8F",
66///     reaction.to_string(),
67/// );
68/// ```
69impl Display for RequestReactionType<'_> {
70    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
71        match self {
72            RequestReactionType::Custom { id, name } => {
73                if let Some(name) = name {
74                    f.write_str(name)?;
75                } else {
76                    f.write_str("e")?;
77                }
78
79                f.write_str(":")?;
80
81                Display::fmt(id, f)
82            }
83            RequestReactionType::Unicode { name } => {
84                Display::fmt(&utf8_percent_encode(name, NON_ALPHANUMERIC), f)
85            }
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    // `clippy::non_ascii_literal` can't be allowed on an item level; it can
93    // only be enabled on a module level.
94    #![allow(clippy::non_ascii_literal)]
95
96    use super::RequestReactionType;
97    use static_assertions::{assert_fields, assert_impl_all};
98    use std::{
99        fmt::{Debug, Display},
100        hash::Hash,
101    };
102    use twilight_model::id::Id;
103
104    assert_fields!(RequestReactionType::Custom: id, name);
105    assert_fields!(RequestReactionType::Unicode: name);
106    assert_impl_all!(RequestReactionType<'_>: Clone, Copy, Debug, Display, Eq, Hash, PartialEq, Send, Sync);
107
108    #[test]
109    fn display_custom_with_name() {
110        let reaction = RequestReactionType::Custom {
111            id: Id::new(123),
112            name: Some("foo"),
113        };
114
115        assert_eq!("foo:123", reaction.to_string());
116    }
117
118    #[test]
119    fn display_custom_without_name() {
120        let reaction = RequestReactionType::Custom {
121            id: Id::new(123),
122            name: None,
123        };
124
125        assert_eq!("e:123", reaction.to_string());
126    }
127
128    /// Test that unicode reactions format with percent encoding.
129    // We can't use the actual flag here
130    #[test]
131    fn display_unicode() {
132        let reaction = RequestReactionType::Unicode {
133            // Rainbow flag 🏳️‍🌈
134            name: "🏳️‍🌈",
135        };
136
137        assert_eq!(
138            "%F0%9F%8F%B3%EF%B8%8F%E2%80%8D%F0%9F%8C%88",
139            reaction.to_string()
140        );
141    }
142}