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
149
150
151
152
153
154
155
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use serde_json::{json, Value};

use crate::model::id::{RoleId, UserId};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ParseValue {
    #[serde(rename = "everyone")]
    Everyone,
    #[serde(rename = "users")]
    Users,
    #[serde(rename = "roles")]
    Roles,
}

/// A builder to manage the allowed mentions on a message,
/// used by the [`ChannelId::send_message`] method.
///
/// # Examples
///
/// ```rust,ignore
/// use serenity::builder::ParseValue;
///
/// // Mention only the user 110372470472613888
/// m.allowed_mentions(|am| {
///     am.empty_parse();
///     am.users(vec![110372470472613888])
/// });
///
/// // Mention all users and the role 182894738100322304
/// m.allowed_mentions(|am| {
///     am.parse(ParseValue::Users);
///     am.roles(vec![182894738100322304])
/// });
///
/// // Mention all roles and nothing else
/// m.allowed_mentions(|am| {
///     am.parse(ParseValue::Roles)
/// });
///
/// // Mention all roles and users, but not everyone
/// m.allowed_mentions(|am| {
///     am.parse(ParseValue::Users);
///     am.parse(ParseValue::Roles)
/// });
///
/// // Mention everyone and the users 182891574139682816, 110372470472613888
/// m.allowed_mentions(|am| {
///     am.parse(ParseValue::Everyone);
///     am.users(vec![182891574139682816, 110372470472613888])
/// });
///
/// // Mention everyone and the message author.
/// m.allowed_mentions(|am| {
///     am.parse(ParseValue::Everyone);
///     am.users(vec![msg.author.id])
/// });
/// ```
///
/// [`ChannelId::send_message`]: crate::model::id::ChannelId::send_message
#[derive(Clone, Debug)]
pub struct CreateAllowedMentions(pub HashMap<&'static str, Value>);

impl CreateAllowedMentions {
    /// Add a value that's allowed to be mentioned.
    ///
    /// If users or roles is specified, [`Self::users`] and [`Self::roles`] will not work.\
    /// If you use either, do not specify it's same type here.
    #[inline]
    pub fn parse(&mut self, value: ParseValue) -> &mut Self {
        let val = self.0.entry("parse").or_insert_with(|| Value::Array(Vec::new()));

        let arr = val.as_array_mut().expect("Must be an array");
        arr.push(json![value]);

        self
    }

    /// Clear all the values that would be mentioned.
    ///
    /// If parse is empty, the message will not mention anyone, unless they are specified on
    /// [`Self::users`] or [`Self::roles`].
    #[inline]
    pub fn empty_parse(&mut self) -> &mut Self {
        let val = self.0.entry("parse").or_insert_with(|| Value::Array(Vec::new()));

        let arr = val.as_array_mut().expect("Must be an array");
        arr.clear();

        self
    }

    /// Sets the users that will be allowed to be mentioned.
    #[inline]
    pub fn users<U: Into<UserId>>(&mut self, users: impl IntoIterator<Item = U>) -> &mut Self {
        self.0.insert(
            "users",
            Value::Array({
                users.into_iter().map(|i| json!(i.into().to_string())).collect::<Vec<_>>()
            }),
        );
        self
    }

    /// Makes users unable to be mentioned.
    #[inline]
    pub fn empty_users(&mut self) -> &mut Self {
        let val = self.0.entry("users").or_insert_with(|| Value::Array(Vec::new()));

        let arr = val.as_array_mut().expect("Must be an array");
        arr.clear();

        self
    }

    /// Sets the roles that will be allowed to be mentioned.
    #[inline]
    pub fn roles<R: Into<RoleId>>(&mut self, users: impl IntoIterator<Item = R>) -> &mut Self {
        self.0.insert(
            "roles",
            Value::Array({
                users.into_iter().map(|i| json!(i.into().to_string())).collect::<Vec<_>>()
            }),
        );
        self
    }

    /// Makes roles unable to be mentioned.
    #[inline]
    pub fn empty_roles(&mut self) -> &mut Self {
        let val = self.0.entry("roles").or_insert_with(|| Value::Array(Vec::new()));

        let arr = val.as_array_mut().expect("Must be an array");
        arr.clear();

        self
    }

    /// Makes the reply mention/ping the user.
    #[inline]
    pub fn replied_user(&mut self, mention_user: bool) -> &mut Self {
        self.0.insert("replied_user", Value::Bool(mention_user));

        self
    }
}

impl Default for CreateAllowedMentions {
    fn default() -> CreateAllowedMentions {
        let map = HashMap::new();
        CreateAllowedMentions(map)
    }
}