serenity/builder/
create_invite.rs

1#[cfg(feature = "http")]
2use super::Builder;
3#[cfg(feature = "http")]
4use crate::http::CacheHttp;
5#[cfg(feature = "http")]
6use crate::internal::prelude::*;
7use crate::model::prelude::*;
8
9/// A builder to create a [`RichInvite`] for use via [`GuildChannel::create_invite`].
10///
11/// This is a structured and cleaner way of creating an invite, as all parameters are optional.
12///
13/// # Examples
14///
15/// Create an invite with a max age of 3600 seconds and 10 max uses:
16///
17/// ```rust,no_run
18/// # use serenity::{prelude::*, model::prelude::*};
19/// use serenity::builder::CreateInvite;
20/// # async fn run(context: impl CacheHttp, channel: GuildChannel) -> Result<(), Box<dyn std::error::Error>> {
21/// let builder = CreateInvite::new().max_age(3600).max_uses(10);
22/// let creation = channel.create_invite(&context, builder).await?;
23/// # Ok(())
24/// # }
25/// ```
26///
27/// [Discord docs](https://discord.com/developers/docs/resources/channel#create-channel-invite)
28#[derive(Clone, Debug, Default, Serialize)]
29#[must_use]
30pub struct CreateInvite<'a> {
31    #[serde(skip_serializing_if = "Option::is_none")]
32    max_age: Option<u32>,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    max_uses: Option<u8>,
35    #[serde(skip_serializing_if = "Option::is_none")]
36    temporary: Option<bool>,
37    #[serde(skip_serializing_if = "Option::is_none")]
38    unique: Option<bool>,
39    #[serde(skip_serializing_if = "Option::is_none")]
40    target_type: Option<InviteTargetType>,
41    #[serde(skip_serializing_if = "Option::is_none")]
42    target_user_id: Option<UserId>,
43    #[serde(skip_serializing_if = "Option::is_none")]
44    target_application_id: Option<ApplicationId>,
45
46    #[serde(skip)]
47    audit_log_reason: Option<&'a str>,
48}
49
50impl<'a> CreateInvite<'a> {
51    /// Equivalent to [`Self::default`].
52    pub fn new() -> Self {
53        Self::default()
54    }
55
56    /// The duration that the invite will be valid for.
57    ///
58    /// Set to `0` for an invite which does not expire after an amount of time.
59    ///
60    /// Defaults to `86400`, or 24 hours.
61    ///
62    /// # Examples
63    ///
64    /// Create an invite with a max age of `3600` seconds, or 1 hour:
65    ///
66    /// ```rust,no_run
67    /// # use serenity::model::prelude::*;
68    /// # use serenity::builder::CreateInvite;
69    /// # use serenity::http::CacheHttp;
70    /// #
71    /// # async fn example(context: impl CacheHttp, channel: GuildChannel) -> Result<(), Box<dyn std::error::Error>> {
72    /// let builder = CreateInvite::new().max_age(3600);
73    /// let invite = channel.create_invite(context, builder).await?;
74    /// # Ok(())
75    /// # }
76    /// ```
77    pub fn max_age(mut self, max_age: u32) -> Self {
78        self.max_age = Some(max_age);
79        self
80    }
81
82    /// The number of uses that the invite will be valid for.
83    ///
84    /// Set to `0` for an invite which does not expire after a number of uses.
85    ///
86    /// Defaults to `0`.
87    ///
88    /// # Examples
89    ///
90    /// Create an invite with a max use limit of `5`:
91    ///
92    /// Create an invite with a max age of `3600` seconds, or 1 hour:
93    ///
94    /// ```rust,no_run
95    /// # use serenity::model::prelude::*;
96    /// # use serenity::builder::CreateInvite;
97    /// # use serenity::http::CacheHttp;
98    /// #
99    /// # async fn example(context: impl CacheHttp, channel: GuildChannel) -> Result<(), Box<dyn std::error::Error>> {
100    /// let builder = CreateInvite::new().max_uses(5);
101    /// let invite = channel.create_invite(context, builder).await?;
102    /// # Ok(())
103    /// # }
104    /// ```
105    pub fn max_uses(mut self, max_uses: u8) -> Self {
106        self.max_uses = Some(max_uses);
107        self
108    }
109
110    /// Whether an invite grants a temporary membership.
111    ///
112    /// Defaults to `false`.
113    ///
114    /// # Examples
115    ///
116    /// Create an invite which is temporary:
117    ///
118    /// ```rust,no_run
119    /// # use serenity::model::prelude::*;
120    /// # use serenity::builder::CreateInvite;
121    /// # use serenity::http::CacheHttp;
122    /// #
123    /// # async fn example(context: impl CacheHttp, channel: GuildChannel) -> Result<(), Box<dyn std::error::Error>> {
124    /// let builder = CreateInvite::new().temporary(true);
125    /// let invite = channel.create_invite(context, builder).await?;
126    /// # Ok(())
127    /// # }
128    /// ```
129    pub fn temporary(mut self, temporary: bool) -> Self {
130        self.temporary = Some(temporary);
131        self
132    }
133
134    /// Whether or not to try to reuse a similar invite.
135    ///
136    /// Defaults to `false`.
137    ///
138    /// # Examples
139    ///
140    /// Create an invite which is unique:
141    ///
142    /// ```rust,no_run
143    /// # use serenity::model::prelude::*;
144    /// # use serenity::builder::CreateInvite;
145    /// # use serenity::http::CacheHttp;
146    /// #
147    /// # async fn example(context: impl CacheHttp, channel: GuildChannel) -> Result<(), Box<dyn std::error::Error>> {
148    /// let builder = CreateInvite::new().unique(true);
149    /// let invite = channel.create_invite(context, builder).await?;
150    /// # Ok(())
151    /// # }
152    /// ```
153    pub fn unique(mut self, unique: bool) -> Self {
154        self.unique = Some(unique);
155        self
156    }
157
158    /// The type of target for this voice channel invite.
159    pub fn target_type(mut self, target_type: InviteTargetType) -> Self {
160        self.target_type = Some(target_type);
161        self
162    }
163
164    /// The ID of the user whose stream to display for this invite, required if `target_type` is
165    /// `Stream`
166    /// The user must be streaming in the channel.
167    pub fn target_user_id(mut self, target_user_id: UserId) -> Self {
168        self.target_user_id = Some(target_user_id);
169        self
170    }
171
172    /// The ID of the embedded application to open for this invite, required if `target_type` is
173    /// `EmmbeddedApplication`.
174    ///
175    /// The application must have the `EMBEDDED` flag.
176    ///
177    /// When sending an invite with this value, the first user to use the invite will have to click
178    /// on the URL, that will enable the buttons in the embed.
179    ///
180    /// These are some of the known applications which have the flag:
181    ///
182    /// betrayal: `773336526917861400`
183    /// youtube: `755600276941176913`
184    /// fishing: `814288819477020702`
185    /// poker: `755827207812677713`
186    /// chess: `832012774040141894`
187    pub fn target_application_id(mut self, target_application_id: ApplicationId) -> Self {
188        self.target_application_id = Some(target_application_id);
189        self
190    }
191
192    /// Sets the request's audit log reason.
193    pub fn audit_log_reason(mut self, reason: &'a str) -> Self {
194        self.audit_log_reason = Some(reason);
195        self
196    }
197}
198
199#[cfg(feature = "http")]
200#[async_trait::async_trait]
201impl Builder for CreateInvite<'_> {
202    type Context<'ctx> = ChannelId;
203    type Built = RichInvite;
204
205    /// Creates an invite for the given channel.
206    ///
207    /// **Note**: Requires the [Create Instant Invite] permission.
208    ///
209    /// # Errors
210    ///
211    /// If the `cache` is enabled, returns [`ModelError::InvalidPermissions`] if the current user
212    /// lacks permission. Otherwise returns [`Error::Http`], as well as if invalid data is given.
213    ///
214    /// [Create Instant Invite]: Permissions::CREATE_INSTANT_INVITE
215    async fn execute(
216        self,
217        cache_http: impl CacheHttp,
218        ctx: Self::Context<'_>,
219    ) -> Result<RichInvite> {
220        #[cfg(feature = "cache")]
221        {
222            if let Some(cache) = cache_http.cache() {
223                crate::utils::user_has_perms_cache(cache, ctx, Permissions::CREATE_INSTANT_INVITE)?;
224            }
225        }
226
227        cache_http.http().create_invite(ctx, &self, self.audit_log_reason).await
228    }
229}