Skip to main content

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