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

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