Skip to main content

twilight_http/request/application/command/create_global_command/
user.rs

1use super::super::CommandBorrowed;
2#[cfg(not(target_os = "wasi"))]
3use crate::response::{Response, ResponseFuture};
4use crate::{
5    client::Client,
6    error::Error,
7    request::{Request, TryIntoRequest},
8    routing::Route,
9};
10use std::{collections::HashMap, future::IntoFuture};
11use twilight_model::{
12    application::command::{Command, CommandType},
13    guild::Permissions,
14    id::{Id, marker::ApplicationMarker},
15};
16use twilight_validate::command::{CommandValidationError, name as validate_name};
17
18struct CreateGlobalUserCommandFields<'a> {
19    default_member_permissions: Option<Permissions>,
20    dm_permission: Option<bool>,
21    name: &'a str,
22    name_localizations: Option<&'a HashMap<String, String>>,
23    nsfw: Option<bool>,
24}
25
26/// Create a new user global command.
27///
28/// Creating a command with the same name as an already-existing global command
29/// will overwrite the old command. See
30/// [Discord Docs/Create Global Application Command].
31///
32/// [Discord Docs/Create Global Application Command]: https://discord.com/developers/docs/interactions/application-commands#create-global-application-command
33#[must_use = "requests must be configured and executed"]
34pub struct CreateGlobalUserCommand<'a> {
35    application_id: Id<ApplicationMarker>,
36    fields: Result<CreateGlobalUserCommandFields<'a>, CommandValidationError>,
37    http: &'a Client,
38}
39
40impl<'a> CreateGlobalUserCommand<'a> {
41    pub(crate) fn new(
42        http: &'a Client,
43        application_id: Id<ApplicationMarker>,
44        name: &'a str,
45    ) -> Self {
46        let fields = Ok(CreateGlobalUserCommandFields {
47            default_member_permissions: None,
48            dm_permission: None,
49            name,
50            name_localizations: None,
51            nsfw: None,
52        })
53        .and_then(|fields| {
54            validate_name(name)?;
55
56            Ok(fields)
57        });
58
59        Self {
60            application_id,
61            fields,
62            http,
63        }
64    }
65
66    /// Default permissions required for a member to run the command.
67    ///
68    /// Defaults to [`None`].
69    pub const fn default_member_permissions(mut self, default: Permissions) -> Self {
70        if let Ok(fields) = self.fields.as_mut() {
71            fields.default_member_permissions = Some(default);
72        }
73
74        self
75    }
76
77    /// Set whether the command is available in DMs.
78    ///
79    /// Defaults to [`None`].
80    pub const fn dm_permission(mut self, dm_permission: bool) -> Self {
81        if let Ok(fields) = self.fields.as_mut() {
82            fields.dm_permission = Some(dm_permission);
83        }
84
85        self
86    }
87
88    /// Set the localization dictionary for the command name.
89    ///
90    /// Defaults to [`None`].
91    ///
92    /// # Errors
93    ///
94    /// Returns an error of type [`NameLengthInvalid`] if the name is invalid.
95    ///
96    /// [`NameLengthInvalid`]: twilight_validate::command::CommandValidationErrorType::NameLengthInvalid
97    pub fn name_localizations(mut self, localizations: &'a HashMap<String, String>) -> Self {
98        self.fields = self.fields.and_then(|mut fields| {
99            for name in localizations.values() {
100                validate_name(name)?;
101            }
102
103            fields.name_localizations = Some(localizations);
104
105            Ok(fields)
106        });
107
108        self
109    }
110
111    /// Set whether the command is age-restricted.
112    ///
113    /// Defaults to not being specified, which uses Discord's default.
114    pub const fn nsfw(mut self, nsfw: bool) -> Self {
115        if let Ok(fields) = self.fields.as_mut() {
116            fields.nsfw = Some(nsfw);
117        }
118
119        self
120    }
121}
122
123#[cfg(not(target_os = "wasi"))]
124impl IntoFuture for CreateGlobalUserCommand<'_> {
125    type Output = Result<Response<Command>, Error>;
126
127    type IntoFuture = ResponseFuture<Command>;
128
129    fn into_future(self) -> Self::IntoFuture {
130        let http = self.http;
131
132        match self.try_into_request() {
133            Ok(request) => http.request(request),
134            Err(source) => ResponseFuture::error(source),
135        }
136    }
137}
138
139impl TryIntoRequest for CreateGlobalUserCommand<'_> {
140    fn try_into_request(self) -> Result<Request, Error> {
141        let fields = self.fields.map_err(Error::validation)?;
142
143        Request::builder(&Route::CreateGlobalCommand {
144            application_id: self.application_id.get(),
145        })
146        .json(&CommandBorrowed {
147            application_id: Some(self.application_id),
148            default_member_permissions: fields.default_member_permissions,
149            dm_permission: fields.dm_permission,
150            description: None,
151            description_localizations: None,
152            kind: CommandType::User,
153            name: fields.name,
154            name_localizations: fields.name_localizations,
155            nsfw: fields.nsfw,
156            options: None,
157        })
158        .build()
159    }
160}