1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use crate::{
    channel::message::allowed_mentions::{AllowedMentions, ParseTypes},
    id::{RoleId, UserId},
};

#[derive(Clone, Default, Debug, Eq, PartialEq)]
pub struct AllowedMentionsBuilder(AllowedMentions);

impl AllowedMentionsBuilder {
    /// Create a new [`AllowedMentionsBuilder`].
    pub const fn new() -> Self {
        Self(AllowedMentions {
            parse: Vec::new(),
            users: Vec::new(),
            roles: Vec::new(),
            replied_user: false,
        })
    }

    /// Allow parsing of `@everyone`.
    pub fn everyone(mut self) -> Self {
        self.0.parse.push(ParseTypes::Everyone);

        self
    }

    /// When replying, whether to mention the target user.
    pub const fn replied_user(mut self) -> Self {
        self.0.replied_user = true;

        self
    }

    /// Allow parsing of all roles.
    pub fn roles(mut self) -> Self {
        self.0.parse.push(ParseTypes::Roles);

        self
    }

    /// Allow parsing of specific [`RoleId`]s.
    ///
    /// [`roles`] and this method are mutually exclusive. The builder will favor
    /// specific role ids.
    ///
    /// [`roles`]: Self::roles
    pub fn role_ids(mut self, role_ids: impl IntoIterator<Item = RoleId>) -> Self {
        self.0.roles.extend(role_ids);

        self
    }

    /// Allow parsing of all users.
    pub fn users(mut self) -> Self {
        self.0.parse.push(ParseTypes::Users);

        self
    }

    /// Allow parsing of  specific [`UserId`]s.
    ///
    /// [`users`] and this method are mutually exclusive. The builder will favor
    /// specific user ids.
    ///
    /// [`users`]: Self::users
    pub fn user_ids(mut self, user_ids: impl IntoIterator<Item = UserId>) -> Self {
        self.0.users.extend(user_ids);

        self
    }

    /// Build the [`AllowedMentions`] struct.
    ///
    /// Note: This clears possible validation errors by removing data.  For
    /// example, if both `users` and `user_ids` are called, the effect of
    /// `users` will be nullified and only the users specified with `user_ids`
    /// will be built.
    pub fn build(mut self) -> AllowedMentions {
        if !self.0.users.is_empty() {
            self.0.parse = self
                .0
                .parse
                .into_iter()
                .filter(|t| *t != ParseTypes::Users)
                .collect();
        }

        if !self.0.roles.is_empty() {
            self.0.parse = self
                .0
                .parse
                .into_iter()
                .filter(|t| *t != ParseTypes::Roles)
                .collect();
        }

        self.0
    }
}

#[cfg(test)]
mod tests {
    use super::{
        super::{AllowedMentions, ParseTypes},
        AllowedMentionsBuilder,
    };
    use crate::id::{RoleId, UserId};

    #[test]
    fn test_max_mentioned() {
        let value = AllowedMentionsBuilder::new()
            .everyone()
            .replied_user()
            .users()
            .roles()
            .build();

        assert_eq!(
            value,
            AllowedMentions {
                parse: vec![ParseTypes::Everyone, ParseTypes::Users, ParseTypes::Roles],
                users: vec![],
                roles: vec![],
                replied_user: true
            },
        );
    }

    #[test]
    fn test_validation() {
        let value = AllowedMentionsBuilder::new()
            .users()
            .user_ids(vec![UserId(100), UserId(200)])
            .roles()
            .role_ids(vec![RoleId(300)])
            .build();

        assert_eq!(
            value,
            AllowedMentions {
                parse: vec![],
                users: vec![UserId(100), UserId(200)],
                roles: vec![RoleId(300)],
                replied_user: false,
            },
        );
    }
}