twilight_http/client/
mod.rs

1mod builder;
2pub(crate) mod connector;
3mod interaction;
4
5pub use self::{builder::ClientBuilder, interaction::InteractionClient};
6
7use crate::request::{
8    application::{
9        emoji::{
10            AddApplicationEmoji, DeleteApplicationEmoji, ListApplicationEmojis,
11            UpdateApplicationEmoji,
12        },
13        monetization::{
14            CreateTestEntitlement, CreateTestEntitlementOwner, DeleteTestEntitlement,
15            GetEntitlements, GetSKUs,
16        },
17    },
18    guild::user::{GetCurrentUserVoiceState, GetUserVoiceState},
19};
20#[allow(deprecated)]
21use crate::{
22    API_VERSION,
23    client::connector::Connector,
24    error::{Error, ErrorType},
25    request::{
26        GetCurrentAuthorizationInformation, GetGateway, GetUserApplicationInfo, GetVoiceRegions,
27        Method, Request, UpdateCurrentUserApplication,
28        channel::{
29            CreatePin, CreateTypingTrigger, DeleteChannel, DeleteChannelPermission, DeletePin,
30            FollowNewsChannel, GetChannel, GetPins, UpdateChannel, UpdateChannelPermission,
31            invite::{CreateInvite, DeleteInvite, GetChannelInvites, GetInvite},
32            message::{
33                CreateMessage, CrosspostMessage, DeleteMessage, DeleteMessages, GetChannelMessages,
34                GetMessage, UpdateMessage,
35            },
36            reaction::{
37                CreateReaction, DeleteAllReaction, DeleteAllReactions, DeleteReaction,
38                GetReactions, RequestReactionType, delete_reaction::TargetUser,
39            },
40            stage::{
41                CreateStageInstance, DeleteStageInstance, GetStageInstance, UpdateStageInstance,
42            },
43            thread::{
44                AddThreadMember, CreateForumThread, CreateThread, CreateThreadFromMessage,
45                GetJoinedPrivateArchivedThreads, GetPrivateArchivedThreads,
46                GetPublicArchivedThreads, GetThreadMember, GetThreadMembers, JoinThread,
47                LeaveThread, RemoveThreadMember, UpdateThread,
48            },
49            webhook::{
50                CreateWebhook, DeleteWebhook, DeleteWebhookMessage, ExecuteWebhook,
51                GetChannelWebhooks, GetWebhook, GetWebhookMessage, UpdateWebhook,
52                UpdateWebhookMessage, UpdateWebhookWithToken,
53            },
54        },
55        guild::{
56            CreateGuildChannel, CreateGuildPrune, DeleteGuild, GetActiveThreads, GetAuditLog,
57            GetGuild, GetGuildChannels, GetGuildInvites, GetGuildOnboarding, GetGuildPreview,
58            GetGuildPruneCount, GetGuildVanityUrl, GetGuildVoiceRegions, GetGuildWebhooks,
59            GetGuildWelcomeScreen, GetGuildWidget, GetGuildWidgetSettings, UpdateCurrentMember,
60            UpdateGuild, UpdateGuildChannelPositions, UpdateGuildMfa, UpdateGuildWelcomeScreen,
61            UpdateGuildWidgetSettings,
62            auto_moderation::{
63                CreateAutoModerationRule, DeleteAutoModerationRule, GetAutoModerationRule,
64                GetGuildAutoModerationRules, UpdateAutoModerationRule,
65            },
66            ban::{CreateBan, DeleteBan, GetBan, GetBans},
67            emoji::{CreateEmoji, DeleteEmoji, GetEmoji, GetEmojis, UpdateEmoji},
68            integration::{DeleteGuildIntegration, GetGuildIntegrations},
69            member::{
70                AddGuildMember, AddRoleToMember, GetGuildMembers, GetMember, RemoveMember,
71                RemoveRoleFromMember, SearchGuildMembers, UpdateGuildMember,
72            },
73            role::{
74                CreateRole, DeleteRole, GetGuildRoleMemberCounts, GetGuildRoles, GetRole,
75                UpdateRole, UpdateRolePositions,
76            },
77            sticker::{
78                CreateGuildSticker, DeleteGuildSticker, GetGuildSticker, GetGuildStickers,
79                UpdateGuildSticker,
80            },
81            update_guild_onboarding::{UpdateGuildOnboarding, UpdateGuildOnboardingFields},
82            user::{UpdateCurrentUserVoiceState, UpdateUserVoiceState},
83        },
84        poll::{EndPoll, GetAnswerVoters},
85        scheduled_event::{
86            CreateGuildScheduledEvent, DeleteGuildScheduledEvent, GetGuildScheduledEvent,
87            GetGuildScheduledEventUsers, GetGuildScheduledEvents, UpdateGuildScheduledEvent,
88        },
89        sticker::{GetNitroStickerPacks, GetSticker},
90        template::{
91            CreateGuildFromTemplate, CreateTemplate, DeleteTemplate, GetTemplate, GetTemplates,
92            SyncTemplate, UpdateTemplate,
93        },
94        user::{
95            CreatePrivateChannel, GetCurrentUser, GetCurrentUserConnections,
96            GetCurrentUserGuildMember, GetCurrentUserGuilds, GetUser, LeaveGuild,
97            UpdateCurrentUser,
98        },
99    },
100    response::ResponseFuture,
101};
102use http::header::{
103    AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, HeaderMap, HeaderValue, USER_AGENT,
104};
105use http_body_util::Full;
106use hyper::body::Bytes;
107use hyper_util::client::legacy::Client as HyperClient;
108use std::{
109    fmt::{Debug, Formatter, Result as FmtResult},
110    ops::Deref,
111    sync::{
112        Arc,
113        atomic::{AtomicBool, Ordering},
114    },
115    time::Duration,
116};
117use twilight_http_ratelimiting::{Endpoint, RateLimiter};
118use twilight_model::{
119    channel::{ChannelType, message::AllowedMentions},
120    guild::{
121        MfaLevel, RolePosition, auto_moderation::AutoModerationEventType,
122        scheduled_event::PrivacyLevel,
123    },
124    http::{channel_position::Position, permission_overwrite::PermissionOverwrite},
125    id::{
126        Id,
127        marker::{
128            ApplicationMarker, AutoModerationRuleMarker, ChannelMarker, EmojiMarker,
129            EntitlementMarker, GuildMarker, IntegrationMarker, MessageMarker, RoleMarker,
130            ScheduledEventMarker, SkuMarker, StickerMarker, UserMarker, WebhookMarker,
131        },
132    },
133};
134
135const TWILIGHT_USER_AGENT: &str = concat!(
136    "DiscordBot (",
137    env!("CARGO_PKG_HOMEPAGE"),
138    ", ",
139    env!("CARGO_PKG_VERSION"),
140    ") Twilight-rs",
141);
142
143/// Wrapper for an authorization token with a debug implementation that redacts
144/// the string.
145#[derive(Default)]
146struct Token {
147    /// Authorization token that is redacted in the Debug implementation.
148    inner: Box<str>,
149}
150
151impl Token {
152    /// Create a new authorization wrapper.
153    const fn new(token: Box<str>) -> Self {
154        Self { inner: token }
155    }
156}
157
158impl Debug for Token {
159    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
160        f.write_str("<redacted>")
161    }
162}
163
164impl Deref for Token {
165    type Target = str;
166
167    fn deref(&self) -> &Self::Target {
168        &self.inner
169    }
170}
171
172/// Twilight's http client.
173///
174/// Almost all of the client methods require authentication, and as such, the client must be
175/// supplied with a Discord Token. Get yours [here].
176///
177/// # Interactions
178///
179/// HTTP interaction requests may be accessed via the [`Client::interaction`]
180/// method.
181///
182/// # OAuth2
183///
184/// To use Bearer tokens prefix the token with `"Bearer "`, including the space
185/// at the end like so:
186///
187/// ```no_run
188/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
189/// use std::env;
190/// use twilight_http::Client;
191///
192/// let bearer = env::var("BEARER_TOKEN")?;
193/// let token = format!("Bearer {bearer}");
194///
195/// let client = Client::new(token);
196/// # Ok(()) }
197/// ```
198///
199/// # Using the client in multiple tasks
200///
201/// To use a client instance in multiple tasks, consider wrapping it in an
202/// [`std::sync::Arc`] or [`std::rc::Rc`].
203///
204/// # Unauthorized behavior
205///
206/// When the client encounters an Unauthorized response it will take note that
207/// the configured token is invalid. This may occur when the token has been
208/// revoked or expired. When this happens, you must create a new client with the
209/// new token. The client will no longer execute requests in order to
210/// prevent API bans and will always return [`ErrorType::Unauthorized`].
211///
212/// # Examples
213///
214/// Create a client called `client`:
215/// ```no_run
216/// use twilight_http::Client;
217///
218/// # #[tokio::main]
219/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
220/// let client = Client::new("my token".to_owned());
221/// # Ok(()) }
222/// ```
223///
224/// Use [`ClientBuilder`] to create a client called `client`, with a shorter
225/// timeout:
226/// ```no_run
227/// use std::time::Duration;
228/// use twilight_http::Client;
229///
230/// # #[tokio::main]
231/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
232/// let client = Client::builder()
233///     .token("my token".to_owned())
234///     .timeout(Duration::from_secs(5))
235///     .build();
236/// # Ok(()) }
237/// ```
238///
239/// All the examples on this page assume you have already created a client, and have named it
240/// `client`.
241///
242/// [here]: https://discord.com/developers/applications
243#[derive(Debug)]
244pub struct Client {
245    pub(crate) default_allowed_mentions: Option<AllowedMentions>,
246    default_headers: Option<HeaderMap>,
247    http: HyperClient<Connector, Full<Bytes>>,
248    proxy: Option<Box<str>>,
249    ratelimiter: Option<RateLimiter>,
250    timeout: Duration,
251    /// Whether the token is invalidated.
252    ///
253    /// Whether an invalid token is tracked can be configured via
254    /// [`ClientBuilder::remember_invalid_token`].
255    token_invalidated: Option<Arc<AtomicBool>>,
256    token: Option<Token>,
257    use_http: bool,
258}
259
260impl Client {
261    /// Create a new client with a token.
262    pub fn new(token: String) -> Self {
263        ClientBuilder::default().token(token).build()
264    }
265
266    /// Create a new builder to create a client.
267    ///
268    /// Refer to its documentation for more information.
269    pub fn builder() -> ClientBuilder {
270        ClientBuilder::new()
271    }
272
273    /// Retrieve an immutable reference to the token used by the client.
274    ///
275    /// If the initial token provided is not prefixed with `Bot `, it will be, and this method
276    /// reflects that.
277    pub fn token(&self) -> Option<&str> {
278        self.token.as_deref()
279    }
280
281    /// Create an interface for using interactions.
282    ///
283    /// An application ID is required to be passed in to use interactions. The
284    /// ID may be retrieved via [`current_user_application`] and cached for use
285    /// with this method.
286    ///
287    /// # Examples
288    ///
289    /// Retrieve the application ID and then use an interaction request:
290    ///
291    /// ```no_run
292    /// # #[tokio::main]
293    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
294    /// use std::env;
295    /// use twilight_http::Client;
296    ///
297    /// let client = Client::new(env::var("DISCORD_TOKEN")?);
298    ///
299    /// // Cache the application ID for repeated use later in the process.
300    /// let application_id = {
301    ///     let response = client.current_user_application().await?;
302    ///
303    ///     response.model().await?.id
304    /// };
305    ///
306    /// // Later in the process...
307    /// let commands = client
308    ///     .interaction(application_id)
309    ///     .global_commands()
310    ///     .await?
311    ///     .models()
312    ///     .await?;
313    ///
314    /// println!("there are {} global commands", commands.len());
315    /// # Ok(()) }
316    /// ```
317    ///
318    /// [`current_user_application`]: Self::current_user_application
319    pub const fn interaction(
320        &self,
321        application_id: Id<ApplicationMarker>,
322    ) -> InteractionClient<'_> {
323        InteractionClient::new(self, application_id)
324    }
325
326    /// Get an immutable reference to the default [`AllowedMentions`] for sent
327    /// messages.
328    pub const fn default_allowed_mentions(&self) -> Option<&AllowedMentions> {
329        self.default_allowed_mentions.as_ref()
330    }
331
332    /// Get the Ratelimiter used by the client internally.
333    ///
334    /// This will return `None` only if ratelimit handling
335    /// has been explicitly disabled in the [`ClientBuilder`].
336    pub const fn ratelimiter(&self) -> Option<&RateLimiter> {
337        self.ratelimiter.as_ref()
338    }
339
340    /// Get an auto moderation rule in a guild.
341    ///
342    /// Requires the [`MANAGE_GUILD`] permission.
343    ///
344    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
345    pub const fn auto_moderation_rule(
346        &self,
347        guild_id: Id<GuildMarker>,
348        auto_moderation_rule_id: Id<AutoModerationRuleMarker>,
349    ) -> GetAutoModerationRule<'_> {
350        GetAutoModerationRule::new(self, guild_id, auto_moderation_rule_id)
351    }
352
353    /// Get the auto moderation rules in a guild.
354    ///
355    /// Requires the [`MANAGE_GUILD`] permission.
356    ///
357    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
358    pub const fn auto_moderation_rules(
359        &self,
360        guild_id: Id<GuildMarker>,
361    ) -> GetGuildAutoModerationRules<'_> {
362        GetGuildAutoModerationRules::new(self, guild_id)
363    }
364
365    /// Create an auto moderation rule within a guild.
366    ///
367    /// Requires the [`MANAGE_GUILD`] permission.
368    ///
369    /// # Examples
370    ///
371    /// Create a rule that deletes messages that contain the word "darn":
372    ///
373    /// ```no_run
374    /// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
375    /// use twilight_http::Client;
376    /// use twilight_model::{guild::auto_moderation::AutoModerationEventType, id::Id};
377    ///
378    /// let client = Client::new("my token".to_owned());
379    ///
380    /// let guild_id = Id::new(1);
381    /// client
382    ///     .create_auto_moderation_rule(guild_id, "no darns", AutoModerationEventType::MessageSend)
383    ///     .action_block_message()
384    ///     .enabled(true)
385    ///     .with_keyword(&["darn"], &["d(?:4|a)rn"], &["darn it"])
386    ///     .await?;
387    /// # Ok(()) }
388    /// ```
389    ///
390    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
391    pub const fn create_auto_moderation_rule<'a>(
392        &'a self,
393        guild_id: Id<GuildMarker>,
394        name: &'a str,
395        event_type: AutoModerationEventType,
396    ) -> CreateAutoModerationRule<'a> {
397        CreateAutoModerationRule::new(self, guild_id, name, event_type)
398    }
399
400    /// Delete an auto moderation rule in a guild.
401    ///
402    /// Requires the [`MANAGE_GUILD`] permission.
403    ///
404    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
405    pub const fn delete_auto_moderation_rule(
406        &self,
407        guild_id: Id<GuildMarker>,
408        auto_moderation_rule_id: Id<AutoModerationRuleMarker>,
409    ) -> DeleteAutoModerationRule<'_> {
410        DeleteAutoModerationRule::new(self, guild_id, auto_moderation_rule_id)
411    }
412
413    /// Update an auto moderation rule in a guild.
414    ///
415    /// Requires the [`MANAGE_GUILD`] permission.
416    ///
417    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
418    pub const fn update_auto_moderation_rule(
419        &self,
420        guild_id: Id<GuildMarker>,
421        auto_moderation_rule_id: Id<AutoModerationRuleMarker>,
422    ) -> UpdateAutoModerationRule<'_> {
423        UpdateAutoModerationRule::new(self, guild_id, auto_moderation_rule_id)
424    }
425
426    /// Get the audit log for a guild.
427    ///
428    /// # Examples
429    ///
430    /// ```no_run
431    /// # use twilight_http::Client;
432    /// use twilight_model::id::Id;
433    ///
434    /// # #[tokio::main]
435    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
436    /// # let client = Client::new("token".to_owned());
437    /// let guild_id = Id::new(101);
438    /// let audit_log = client.audit_log(guild_id).await?;
439    /// # Ok(()) }
440    /// ```
441    pub const fn audit_log(&self, guild_id: Id<GuildMarker>) -> GetAuditLog<'_> {
442        GetAuditLog::new(self, guild_id)
443    }
444
445    /// Retrieve the bans for a guild.
446    ///
447    /// # Examples
448    ///
449    /// Retrieve the bans for guild `1`:
450    ///
451    /// ```no_run
452    /// # use twilight_http::Client;
453    /// use twilight_model::id::Id;
454    /// #
455    /// # #[tokio::main]
456    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
457    /// # let client = Client::new("my token".to_owned());
458    /// #
459    /// let guild_id = Id::new(1);
460    ///
461    /// let bans = client.bans(guild_id).await?;
462    /// # Ok(()) }
463    /// ```
464    pub const fn bans(&self, guild_id: Id<GuildMarker>) -> GetBans<'_> {
465        GetBans::new(self, guild_id)
466    }
467
468    /// Get information about a ban of a guild.
469    ///
470    /// Includes the user banned and the reason.
471    pub const fn ban(&self, guild_id: Id<GuildMarker>, user_id: Id<UserMarker>) -> GetBan<'_> {
472        GetBan::new(self, guild_id, user_id)
473    }
474
475    /// Bans a user from a guild, optionally with the number of seconds' worth of
476    /// messages to delete and the reason.
477    ///
478    /// # Examples
479    ///
480    /// Ban user `200` from guild `100`, deleting
481    /// `86_400` second's (this is equivalent to `1` day) worth of messages, for the reason `"memes"`:
482    ///
483    /// ```no_run
484    /// # use twilight_http::{request::AuditLogReason, Client};
485    /// use twilight_model::id::Id;
486    /// #
487    /// # #[tokio::main]
488    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
489    /// # let client = Client::new("my token".to_owned());
490    /// #
491    /// let guild_id = Id::new(100);
492    /// let user_id = Id::new(200);
493    /// client
494    ///     .create_ban(guild_id, user_id)
495    ///     .delete_message_seconds(86_400)
496    ///     .reason("memes")
497    ///     .await?;
498    /// # Ok(()) }
499    /// ```
500    pub const fn create_ban(
501        &self,
502        guild_id: Id<GuildMarker>,
503        user_id: Id<UserMarker>,
504    ) -> CreateBan<'_> {
505        CreateBan::new(self, guild_id, user_id)
506    }
507
508    /// Remove a ban from a user in a guild.
509    ///
510    /// # Examples
511    ///
512    /// Unban user `200` from guild `100`:
513    ///
514    /// ```no_run
515    /// # use twilight_http::Client;
516    /// use twilight_model::id::Id;
517    /// #
518    /// # #[tokio::main]
519    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
520    /// # let client = Client::new("my token".to_owned());
521    /// #
522    /// let guild_id = Id::new(100);
523    /// let user_id = Id::new(200);
524    ///
525    /// client.delete_ban(guild_id, user_id).await?;
526    /// # Ok(()) }
527    /// ```
528    pub const fn delete_ban(
529        &self,
530        guild_id: Id<GuildMarker>,
531        user_id: Id<UserMarker>,
532    ) -> DeleteBan<'_> {
533        DeleteBan::new(self, guild_id, user_id)
534    }
535
536    /// Get a channel by its ID.
537    ///
538    /// # Examples
539    ///
540    /// Get channel `100`:
541    ///
542    /// ```no_run
543    /// # use twilight_http::Client;
544    /// # use twilight_model::id::Id;
545    /// #
546    /// # #[tokio::main]
547    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
548    /// # let client = Client::new("my token".to_owned());
549    /// #
550    /// let channel_id = Id::new(100);
551    /// #
552    /// let channel = client.channel(channel_id).await?;
553    /// # Ok(()) }
554    /// ```
555    pub const fn channel(&self, channel_id: Id<ChannelMarker>) -> GetChannel<'_> {
556        GetChannel::new(self, channel_id)
557    }
558
559    /// Delete a channel by ID.
560    pub const fn delete_channel(&self, channel_id: Id<ChannelMarker>) -> DeleteChannel<'_> {
561        DeleteChannel::new(self, channel_id)
562    }
563
564    /// Update a channel.
565    pub const fn update_channel(&self, channel_id: Id<ChannelMarker>) -> UpdateChannel<'_> {
566        UpdateChannel::new(self, channel_id)
567    }
568
569    /// Follows a news channel by [`Id<ChannelMarker>`].
570    ///
571    /// The type returned is [`FollowedChannel`].
572    ///
573    /// [`FollowedChannel`]: ::twilight_model::channel::FollowedChannel
574    pub const fn follow_news_channel(
575        &self,
576        channel_id: Id<ChannelMarker>,
577        webhook_channel_id: Id<ChannelMarker>,
578    ) -> FollowNewsChannel<'_> {
579        FollowNewsChannel::new(self, channel_id, webhook_channel_id)
580    }
581
582    /// Get the invites for a guild channel.
583    ///
584    /// Requires the [`MANAGE_CHANNELS`] permission. This method only works if
585    /// the channel is a guild channel.
586    ///
587    /// [`MANAGE_CHANNELS`]: twilight_model::guild::Permissions::MANAGE_CHANNELS
588    pub const fn channel_invites(&self, channel_id: Id<ChannelMarker>) -> GetChannelInvites<'_> {
589        GetChannelInvites::new(self, channel_id)
590    }
591
592    /// Get channel messages, by [`Id<ChannelMarker>`].
593    ///
594    /// Only one of [`after`], [`around`], and [`before`] can be specified at a time.
595    /// Once these are specified, the type returned is [`GetChannelMessagesConfigured`].
596    ///
597    /// If [`limit`] is unspecified, the default set by Discord is 50.
598    ///
599    /// # Examples
600    ///
601    /// ```no_run
602    /// use twilight_http::Client;
603    /// use twilight_model::id::Id;
604    ///
605    /// # #[tokio::main]
606    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
607    /// let client = Client::new("my token".to_owned());
608    /// let channel_id = Id::new(123);
609    /// let message_id = Id::new(234);
610    /// let limit: u16 = 6;
611    ///
612    /// let messages = client
613    ///     .channel_messages(channel_id)
614    ///     .before(message_id)
615    ///     .limit(limit)
616    ///     .await?;
617    ///
618    /// # Ok(()) }
619    /// ```
620    ///
621    /// # Errors
622    ///
623    /// Returns an error of type [`ValidationErrorType::GetChannelMessages`] if
624    /// the amount is less than 1 or greater than 100.
625    ///
626    /// [`GetChannelMessagesConfigured`]: crate::request::channel::message::GetChannelMessagesConfigured
627    /// [`ValidationErrorType::GetChannelMessages`]: twilight_validate::request::ValidationErrorType::GetChannelMessages
628    /// [`after`]: GetChannelMessages::after
629    /// [`around`]: GetChannelMessages::around
630    /// [`before`]: GetChannelMessages::before
631    /// [`limit`]: GetChannelMessages::limit
632    pub const fn channel_messages(&self, channel_id: Id<ChannelMarker>) -> GetChannelMessages<'_> {
633        GetChannelMessages::new(self, channel_id)
634    }
635
636    pub const fn delete_channel_permission(
637        &self,
638        channel_id: Id<ChannelMarker>,
639    ) -> DeleteChannelPermission<'_> {
640        DeleteChannelPermission::new(self, channel_id)
641    }
642
643    /// Update the permissions for a role or a user in a channel.
644    ///
645    /// # Examples:
646    ///
647    /// Create permission overrides for a role to view the channel, but not send
648    /// messages:
649    ///
650    /// ```no_run
651    /// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
652    /// # use twilight_http::Client;
653    /// # let client = Client::new("my token".to_owned());
654    /// #
655    /// use twilight_model::{
656    ///     guild::Permissions,
657    ///     http::permission_overwrite::{PermissionOverwrite, PermissionOverwriteType},
658    ///     id::{Id, marker::RoleMarker},
659    /// };
660    ///
661    /// let channel_id = Id::new(123);
662    /// let role_id: Id<RoleMarker> = Id::new(432);
663    /// let permission_overwrite = PermissionOverwrite {
664    ///     allow: Some(Permissions::VIEW_CHANNEL),
665    ///     deny: Some(Permissions::SEND_MESSAGES),
666    ///     id: role_id.cast(),
667    ///     kind: PermissionOverwriteType::Role,
668    /// };
669    ///
670    /// client
671    ///     .update_channel_permission(channel_id, &permission_overwrite)
672    ///     .await?;
673    /// # Ok(()) }
674    /// ```
675    pub const fn update_channel_permission(
676        &self,
677        channel_id: Id<ChannelMarker>,
678        permission_overwrite: &PermissionOverwrite,
679    ) -> UpdateChannelPermission<'_> {
680        UpdateChannelPermission::new(self, channel_id, permission_overwrite)
681    }
682
683    /// Get all the webhooks of a channel.
684    pub const fn channel_webhooks(&self, channel_id: Id<ChannelMarker>) -> GetChannelWebhooks<'_> {
685        GetChannelWebhooks::new(self, channel_id)
686    }
687
688    /// Get information about the current user.
689    pub const fn current_user(&self) -> GetCurrentUser<'_> {
690        GetCurrentUser::new(self)
691    }
692
693    /// Get information about the current user in a guild.
694    pub const fn current_user_guild_member(
695        &self,
696        guild_id: Id<GuildMarker>,
697    ) -> GetCurrentUserGuildMember<'_> {
698        GetCurrentUserGuildMember::new(self, guild_id)
699    }
700
701    /// Get information about the current OAuth2 authorization.
702    pub const fn current_authorization(&self) -> GetCurrentAuthorizationInformation<'_> {
703        GetCurrentAuthorizationInformation::new(self)
704    }
705
706    /// Get information about the current bot application.
707    pub const fn current_user_application(&self) -> GetUserApplicationInfo<'_> {
708        GetUserApplicationInfo::new(self)
709    }
710
711    /// Update the current user's application.
712    pub const fn update_current_user_application(&self) -> UpdateCurrentUserApplication<'_> {
713        UpdateCurrentUserApplication::new(self)
714    }
715
716    /// Update the current user.
717    ///
718    /// All parameters are optional. If the username is changed, it may cause the discriminator to
719    /// be randomized.
720    pub const fn update_current_user(&self) -> UpdateCurrentUser<'_> {
721        UpdateCurrentUser::new(self)
722    }
723
724    /// Get voice state of the current user in a guild.
725    ///
726    /// # Caveats
727    ///
728    /// - Current user must already have joined a voice/stage channel in this guild.
729    pub const fn current_user_voice_state(
730        &self,
731        guild_id: Id<GuildMarker>,
732    ) -> GetCurrentUserVoiceState<'_> {
733        GetCurrentUserVoiceState::new(self, guild_id)
734    }
735
736    /// Update the current user's voice state.
737    ///
738    /// All parameters are optional.
739    ///
740    /// # Caveats
741    ///
742    /// - `channel_id` must currently point to a stage channel.
743    /// - Current user must have already joined `channel_id`.
744    pub const fn update_current_user_voice_state(
745        &self,
746        guild_id: Id<GuildMarker>,
747    ) -> UpdateCurrentUserVoiceState<'_> {
748        UpdateCurrentUserVoiceState::new(self, guild_id)
749    }
750
751    /// Get the current user's connections.
752    ///
753    /// Requires the `connections` `OAuth2` scope.
754    pub const fn current_user_connections(&self) -> GetCurrentUserConnections<'_> {
755        GetCurrentUserConnections::new(self)
756    }
757
758    /// Returns a list of guilds for the current user.
759    ///
760    /// # Examples
761    ///
762    /// Get the first 25 guilds with an ID after `300` and before
763    /// `400`:
764    ///
765    /// ```no_run
766    /// # use twilight_http::Client;
767    /// use twilight_model::id::Id;
768    ///
769    /// # #[tokio::main]
770    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
771    /// # let client = Client::new("my token".to_owned());
772    /// #
773    /// let after = Id::new(300);
774    /// let before = Id::new(400);
775    /// let guilds = client
776    ///     .current_user_guilds()
777    ///     .after(after)
778    ///     .before(before)
779    ///     .limit(25)
780    ///     .await?;
781    /// # Ok(()) }
782    /// ```
783    pub const fn current_user_guilds(&self) -> GetCurrentUserGuilds<'_> {
784        GetCurrentUserGuilds::new(self)
785    }
786
787    /// Get the emojis for a guild, by the guild's id.
788    ///
789    /// # Examples
790    ///
791    /// Get the emojis for guild `100`:
792    ///
793    /// ```no_run
794    /// # use twilight_http::Client;
795    /// # use twilight_model::id::Id;
796    /// #
797    /// # #[tokio::main]
798    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
799    /// # let client = Client::new("my token".to_owned());
800    /// #
801    /// let guild_id = Id::new(100);
802    ///
803    /// client.emojis(guild_id).await?;
804    /// # Ok(()) }
805    /// ```
806    pub const fn emojis(&self, guild_id: Id<GuildMarker>) -> GetEmojis<'_> {
807        GetEmojis::new(self, guild_id)
808    }
809
810    /// Get the entitlements for an application.
811    ///
812    /// # Examples
813    ///
814    /// Get entitlements for the application `100`:
815    ///
816    /// ```no_run
817    /// # use twilight_http::Client;
818    /// # use twilight_model::id::Id;
819    ///
820    /// # #[tokio::main]
821    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
822    /// # let client = Client::new("my token".to_owned());
823    /// #
824    /// let application_id = Id::new(100);
825    ///
826    /// client.entitlements(application_id).await?;
827    /// # Ok(()) }
828    /// ```
829    pub const fn entitlements(&self, application_id: Id<ApplicationMarker>) -> GetEntitlements<'_> {
830        GetEntitlements::new(self, application_id)
831    }
832
833    /// Get an emoji for a guild by the the guild's ID and emoji's ID.
834    ///
835    /// # Examples
836    ///
837    /// Get emoji `100` from guild `50`:
838    ///
839    /// ```no_run
840    /// # use twilight_http::Client;
841    /// # use twilight_model::id::Id;
842    /// #
843    /// # #[tokio::main]
844    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
845    /// # let client = Client::new("my token".to_owned());
846    /// #
847    /// let guild_id = Id::new(50);
848    /// let emoji_id = Id::new(100);
849    ///
850    /// client.emoji(guild_id, emoji_id).await?;
851    /// # Ok(()) }
852    /// ```
853    pub const fn emoji(
854        &self,
855        guild_id: Id<GuildMarker>,
856        emoji_id: Id<EmojiMarker>,
857    ) -> GetEmoji<'_> {
858        GetEmoji::new(self, guild_id, emoji_id)
859    }
860
861    /// Create an emoji in a guild.
862    ///
863    /// The emoji must be a Data URI, in the form of
864    /// `data:image/{type};base64,{data}` where `{type}` is the image MIME type
865    /// and `{data}` is the base64-encoded image. See [Discord Docs/Image Data].
866    ///
867    /// [Discord Docs/Image Data]: https://discord.com/developers/docs/reference#image-data
868    pub const fn create_emoji<'a>(
869        &'a self,
870        guild_id: Id<GuildMarker>,
871        name: &'a str,
872        image: &'a str,
873    ) -> CreateEmoji<'a> {
874        CreateEmoji::new(self, guild_id, name, image)
875    }
876
877    /// Delete an emoji in a guild, by id.
878    pub const fn delete_emoji(
879        &self,
880        guild_id: Id<GuildMarker>,
881        emoji_id: Id<EmojiMarker>,
882    ) -> DeleteEmoji<'_> {
883        DeleteEmoji::new(self, guild_id, emoji_id)
884    }
885
886    /// Update an emoji in a guild, by id.
887    pub const fn update_emoji(
888        &self,
889        guild_id: Id<GuildMarker>,
890        emoji_id: Id<EmojiMarker>,
891    ) -> UpdateEmoji<'_> {
892        UpdateEmoji::new(self, guild_id, emoji_id)
893    }
894
895    /// Get information about the gateway, optionally with additional information detailing the
896    /// number of shards to use and sessions remaining.
897    ///
898    /// # Examples
899    ///
900    /// Get the gateway connection URL without bot information:
901    ///
902    /// ```no_run
903    /// # use twilight_http::Client;
904    /// #
905    /// # #[tokio::main]
906    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
907    /// # let client = Client::new("my token".to_owned());
908    /// #
909    /// let info = client.gateway().await?;
910    /// # Ok(()) }
911    /// ```
912    ///
913    /// Get the gateway connection URL with additional shard and session information, which
914    /// requires specifying a bot token:
915    ///
916    /// ```no_run
917    /// # use twilight_http::Client;
918    /// #
919    /// # #[tokio::main]
920    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
921    /// # let client = Client::new("my token".to_owned());
922    /// #
923    /// let info = client.gateway().authed().await?.model().await?;
924    ///
925    /// println!("URL: {}", info.url);
926    /// println!("Recommended shards to use: {}", info.shards);
927    /// # Ok(()) }
928    /// ```
929    pub const fn gateway(&self) -> GetGateway<'_> {
930        GetGateway::new(self)
931    }
932
933    /// Get information about a guild.
934    pub const fn guild(&self, guild_id: Id<GuildMarker>) -> GetGuild<'_> {
935        GetGuild::new(self, guild_id)
936    }
937
938    /// Delete a guild permanently. The user must be the owner.
939    pub const fn delete_guild(&self, guild_id: Id<GuildMarker>) -> DeleteGuild<'_> {
940        DeleteGuild::new(self, guild_id)
941    }
942
943    /// Update a guild.
944    ///
945    /// All endpoints are optional. See [Discord Docs/Modify Guild].
946    ///
947    /// [Discord Docs/Modify Guild]: https://discord.com/developers/docs/resources/guild#modify-guild
948    pub const fn update_guild(&self, guild_id: Id<GuildMarker>) -> UpdateGuild<'_> {
949        UpdateGuild::new(self, guild_id)
950    }
951
952    /// Leave a guild by id.
953    pub const fn leave_guild(&self, guild_id: Id<GuildMarker>) -> LeaveGuild<'_> {
954        LeaveGuild::new(self, guild_id)
955    }
956
957    /// Get the channels in a guild.
958    pub const fn guild_channels(&self, guild_id: Id<GuildMarker>) -> GetGuildChannels<'_> {
959        GetGuildChannels::new(self, guild_id)
960    }
961
962    /// Create a new request to create a guild channel.
963    ///
964    /// All fields are optional except for name. The minimum length of the name
965    /// is 1 UTF-16 character and the maximum is 100 UTF-16 characters.
966    ///
967    /// # Errors
968    ///
969    /// Returns an error of type [`NameInvalid`] when the length of the name is
970    /// either fewer than 1 UTF-16 character or more than 100 UTF-16 characters.
971    ///
972    /// Returns an error of type [`RateLimitPerUserInvalid`] when the seconds of
973    /// the rate limit per user is more than 21600.
974    ///
975    /// Returns an error of type [`TopicInvalid`] when the length of the topic
976    /// is more than 1024 UTF-16 characters.
977    ///
978    /// [`NameInvalid`]: twilight_validate::channel::ChannelValidationErrorType::NameInvalid
979    /// [`RateLimitPerUserInvalid`]: twilight_validate::channel::ChannelValidationErrorType::RateLimitPerUserInvalid
980    /// [`TopicInvalid`]: twilight_validate::channel::ChannelValidationErrorType::TopicInvalid
981    pub fn create_guild_channel<'a>(
982        &'a self,
983        guild_id: Id<GuildMarker>,
984        name: &'a str,
985    ) -> CreateGuildChannel<'a> {
986        CreateGuildChannel::new(self, guild_id, name)
987    }
988
989    /// Modify the guild onboarding flow.
990    pub const fn update_guild_onboarding(
991        &self,
992        guild_id: Id<GuildMarker>,
993        fields: UpdateGuildOnboardingFields,
994    ) -> UpdateGuildOnboarding<'_> {
995        UpdateGuildOnboarding::new(self, guild_id, fields)
996    }
997
998    /// Modify the positions of the channels.
999    ///
1000    /// The minimum amount of channels to modify, is a swap between two channels.
1001    pub const fn update_guild_channel_positions<'a>(
1002        &'a self,
1003        guild_id: Id<GuildMarker>,
1004        channel_positions: &'a [Position],
1005    ) -> UpdateGuildChannelPositions<'a> {
1006        UpdateGuildChannelPositions::new(self, guild_id, channel_positions)
1007    }
1008
1009    /// Get a guild's widget.
1010    ///
1011    /// See [Discord Docs/Get Guild Widget].
1012    ///
1013    /// [Discord Docs/Get Guild Widget]: https://discord.com/developers/docs/resources/guild#get-guild-widget
1014    pub const fn guild_widget(&self, guild_id: Id<GuildMarker>) -> GetGuildWidget<'_> {
1015        GetGuildWidget::new(self, guild_id)
1016    }
1017
1018    /// Get a guild's widget settings.
1019    ///
1020    /// See [Discord Docs/Get Guild Widget Settings].
1021    ///
1022    /// [Discord Docs/Get Guild Widget]: https://discord.com/developers/docs/resources/guild#get-guild-widget-settings
1023    pub const fn guild_widget_settings(
1024        &self,
1025        guild_id: Id<GuildMarker>,
1026    ) -> GetGuildWidgetSettings<'_> {
1027        GetGuildWidgetSettings::new(self, guild_id)
1028    }
1029
1030    /// Modify a guild's widget.
1031    ///
1032    /// See [Discord Docs/Modify Guild Widget].
1033    ///
1034    /// [Discord Docs/Modify Guild Widget]: https://discord.com/developers/docs/resources/guild#modify-guild-widget
1035    pub const fn update_guild_widget_settings(
1036        &self,
1037        guild_id: Id<GuildMarker>,
1038    ) -> UpdateGuildWidgetSettings<'_> {
1039        UpdateGuildWidgetSettings::new(self, guild_id)
1040    }
1041
1042    /// Get the guild's integrations.
1043    pub const fn guild_integrations(&self, guild_id: Id<GuildMarker>) -> GetGuildIntegrations<'_> {
1044        GetGuildIntegrations::new(self, guild_id)
1045    }
1046
1047    /// Delete an integration for a guild, by the integration's id.
1048    pub const fn delete_guild_integration(
1049        &self,
1050        guild_id: Id<GuildMarker>,
1051        integration_id: Id<IntegrationMarker>,
1052    ) -> DeleteGuildIntegration<'_> {
1053        DeleteGuildIntegration::new(self, guild_id, integration_id)
1054    }
1055
1056    /// Get information about the invites of a guild.
1057    ///
1058    /// Requires the [`MANAGE_GUILD`] permission.
1059    ///
1060    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
1061    pub const fn guild_invites(&self, guild_id: Id<GuildMarker>) -> GetGuildInvites<'_> {
1062        GetGuildInvites::new(self, guild_id)
1063    }
1064
1065    /// Update a guild's MFA level.
1066    pub const fn update_guild_mfa(
1067        &self,
1068        guild_id: Id<GuildMarker>,
1069        level: MfaLevel,
1070    ) -> UpdateGuildMfa<'_> {
1071        UpdateGuildMfa::new(self, guild_id, level)
1072    }
1073
1074    /// Get the members of a guild, by id.
1075    ///
1076    /// The upper limit to this request is 1000. If more than 1000 members are needed, the requests
1077    /// must be chained. Discord defaults the limit to 1.
1078    ///
1079    /// # Examples
1080    ///
1081    /// Get the first 500 members of guild `100` after user ID `3000`:
1082    ///
1083    /// ```no_run
1084    /// # use twilight_http::Client;
1085    /// use twilight_model::id::Id;
1086    /// #
1087    /// # #[tokio::main]
1088    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
1089    /// # let client = Client::new("my token".to_owned());
1090    /// #
1091    /// let guild_id = Id::new(100);
1092    /// let user_id = Id::new(3000);
1093    /// let members = client
1094    ///     .guild_members(guild_id)
1095    ///     .after(user_id)
1096    ///     .limit(500)
1097    ///     .await?;
1098    /// # Ok(()) }
1099    /// ```
1100    ///
1101    /// # Errors
1102    ///
1103    /// Returns an error of type [`ValidationErrorType::GetGuildMembers`] if the
1104    /// limit is invalid.
1105    ///
1106    /// [`ValidationErrorType::GetGuildMembers`]: twilight_validate::request::ValidationErrorType::GetGuildMembers
1107    pub const fn guild_members(&self, guild_id: Id<GuildMarker>) -> GetGuildMembers<'_> {
1108        GetGuildMembers::new(self, guild_id)
1109    }
1110
1111    /// Search the members of a specific guild by a query.
1112    ///
1113    /// The upper limit to this request is 1000. Discord defaults the limit to 1.
1114    ///
1115    /// # Examples
1116    ///
1117    /// Get the first 10 members of guild `100` matching `Wumpus`:
1118    ///
1119    /// ```no_run
1120    /// use twilight_http::Client;
1121    /// use twilight_model::id::Id;
1122    ///
1123    /// # #[tokio::main]
1124    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
1125    /// let client = Client::new("my token".to_owned());
1126    ///
1127    /// let guild_id = Id::new(100);
1128    /// let members = client
1129    ///     .search_guild_members(guild_id, "Wumpus")
1130    ///     .limit(10)
1131    ///     .await?;
1132    /// # Ok(()) }
1133    /// ```
1134    ///
1135    /// # Errors
1136    ///
1137    /// Returns an error of type [`ValidationErrorType::SearchGuildMembers`] if
1138    /// the limit is invalid.
1139    ///
1140    /// [`GUILD_MEMBERS`]: twilight_model::gateway::Intents::GUILD_MEMBERS
1141    /// [`ValidationErrorType::SearchGuildMembers`]: twilight_validate::request::ValidationErrorType::SearchGuildMembers
1142    pub const fn search_guild_members<'a>(
1143        &'a self,
1144        guild_id: Id<GuildMarker>,
1145        query: &'a str,
1146    ) -> SearchGuildMembers<'a> {
1147        SearchGuildMembers::new(self, guild_id, query)
1148    }
1149
1150    /// Get a member of a guild, by their id.
1151    pub const fn guild_member(
1152        &self,
1153        guild_id: Id<GuildMarker>,
1154        user_id: Id<UserMarker>,
1155    ) -> GetMember<'_> {
1156        GetMember::new(self, guild_id, user_id)
1157    }
1158
1159    /// Add a user to a guild.
1160    ///
1161    /// An access token for the user with `guilds.join` scope is required. All
1162    /// other fields are optional. See [Discord Docs/Add Guild Member].
1163    ///
1164    /// # Errors
1165    ///
1166    /// Returns an error of type [`ValidationErrorType::Nickname`] if the
1167    /// nickname is too short or too long.
1168    ///
1169    /// [`ValidationErrorType::Nickname`]: twilight_validate::request::ValidationErrorType::Nickname
1170    /// [Discord Docs/Add Guild Member]: https://discord.com/developers/docs/resources/guild#add-guild-member
1171    pub const fn add_guild_member<'a>(
1172        &'a self,
1173        guild_id: Id<GuildMarker>,
1174        user_id: Id<UserMarker>,
1175        access_token: &'a str,
1176    ) -> AddGuildMember<'a> {
1177        AddGuildMember::new(self, guild_id, user_id, access_token)
1178    }
1179
1180    /// Kick a member from a guild.
1181    pub const fn remove_guild_member(
1182        &self,
1183        guild_id: Id<GuildMarker>,
1184        user_id: Id<UserMarker>,
1185    ) -> RemoveMember<'_> {
1186        RemoveMember::new(self, guild_id, user_id)
1187    }
1188
1189    /// Update a guild member.
1190    ///
1191    /// All fields are optional. See [Discord Docs/Modify Guild Member].
1192    ///
1193    /// # Examples
1194    ///
1195    /// Update a member's nickname to "pinky pie" and server mute them:
1196    ///
1197    /// ```no_run
1198    /// use std::env;
1199    /// use twilight_http::Client;
1200    /// use twilight_model::id::Id;
1201    ///
1202    /// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
1203    /// let client = Client::new(env::var("DISCORD_TOKEN")?);
1204    /// let member = client
1205    ///     .update_guild_member(Id::new(1), Id::new(2))
1206    ///     .mute(true)
1207    ///     .nick(Some("pinkie pie"))
1208    ///     .await?
1209    ///     .model()
1210    ///     .await?;
1211    ///
1212    /// println!(
1213    ///     "user {} now has the nickname '{:?}'",
1214    ///     member.user.id, member.nick,
1215    /// );
1216    /// # Ok(()) }
1217    /// ```
1218    ///
1219    /// # Errors
1220    ///
1221    /// Returns an error of type [`ValidationErrorType::Nickname`] if the
1222    /// nickname length is too short or too long.
1223    ///
1224    /// [`ValidationErrorType::Nickname`]: twilight_validate::request::ValidationErrorType::Nickname
1225    /// [Discord Docs/Modify Guild Member]: https://discord.com/developers/docs/resources/guild#modify-guild-member
1226    pub const fn update_guild_member(
1227        &self,
1228        guild_id: Id<GuildMarker>,
1229        user_id: Id<UserMarker>,
1230    ) -> UpdateGuildMember<'_> {
1231        UpdateGuildMember::new(self, guild_id, user_id)
1232    }
1233
1234    /// Update the user's member in a guild.
1235    pub const fn update_current_member(
1236        &self,
1237        guild_id: Id<GuildMarker>,
1238    ) -> UpdateCurrentMember<'_> {
1239        UpdateCurrentMember::new(self, guild_id)
1240    }
1241
1242    /// Add a role to a member in a guild.
1243    ///
1244    /// # Examples
1245    ///
1246    /// In guild `1`, add role `2` to user `3`, for the reason `"test"`:
1247    ///
1248    /// ```no_run
1249    /// # use twilight_http::{request::AuditLogReason, Client};
1250    /// use twilight_model::id::Id;
1251    /// #
1252    /// # #[tokio::main]
1253    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
1254    /// # let client = Client::new("my token".to_owned());
1255    /// #
1256    /// let guild_id = Id::new(1);
1257    /// let role_id = Id::new(2);
1258    /// let user_id = Id::new(3);
1259    ///
1260    /// client
1261    ///     .add_guild_member_role(guild_id, user_id, role_id)
1262    ///     .reason("test")
1263    ///     .await?;
1264    /// # Ok(()) }
1265    /// ```
1266    pub const fn add_guild_member_role(
1267        &self,
1268        guild_id: Id<GuildMarker>,
1269        user_id: Id<UserMarker>,
1270        role_id: Id<RoleMarker>,
1271    ) -> AddRoleToMember<'_> {
1272        AddRoleToMember::new(self, guild_id, user_id, role_id)
1273    }
1274
1275    /// Remove a role from a member in a guild, by id.
1276    pub const fn remove_guild_member_role(
1277        &self,
1278        guild_id: Id<GuildMarker>,
1279        user_id: Id<UserMarker>,
1280        role_id: Id<RoleMarker>,
1281    ) -> RemoveRoleFromMember<'_> {
1282        RemoveRoleFromMember::new(self, guild_id, user_id, role_id)
1283    }
1284
1285    /// Retrieves the onboarding data for a guild.
1286    pub const fn guild_onboarding(&self, guild_id: Id<GuildMarker>) -> GetGuildOnboarding<'_> {
1287        GetGuildOnboarding::new(self, guild_id)
1288    }
1289
1290    /// For public guilds, get the guild preview.
1291    ///
1292    /// This works even if the user is not in the guild.
1293    pub const fn guild_preview(&self, guild_id: Id<GuildMarker>) -> GetGuildPreview<'_> {
1294        GetGuildPreview::new(self, guild_id)
1295    }
1296
1297    /// Get the counts of guild members to be pruned.
1298    pub const fn guild_prune_count(&self, guild_id: Id<GuildMarker>) -> GetGuildPruneCount<'_> {
1299        GetGuildPruneCount::new(self, guild_id)
1300    }
1301
1302    /// Begin a guild prune.
1303    ///
1304    /// See [Discord Docs/Begin Guild Prune].
1305    ///
1306    /// [Discord Docs/Begin Guild Prune]: https://discord.com/developers/docs/resources/guild#begin-guild-prune
1307    pub const fn create_guild_prune(&self, guild_id: Id<GuildMarker>) -> CreateGuildPrune<'_> {
1308        CreateGuildPrune::new(self, guild_id)
1309    }
1310
1311    /// Get a guild's vanity url, if there is one.
1312    pub const fn guild_vanity_url(&self, guild_id: Id<GuildMarker>) -> GetGuildVanityUrl<'_> {
1313        GetGuildVanityUrl::new(self, guild_id)
1314    }
1315
1316    /// Get voice region data for the guild.
1317    ///
1318    /// Can return VIP servers if the guild is VIP-enabled.
1319    pub const fn guild_voice_regions(&self, guild_id: Id<GuildMarker>) -> GetGuildVoiceRegions<'_> {
1320        GetGuildVoiceRegions::new(self, guild_id)
1321    }
1322
1323    /// Get the webhooks of a guild.
1324    pub const fn guild_webhooks(&self, guild_id: Id<GuildMarker>) -> GetGuildWebhooks<'_> {
1325        GetGuildWebhooks::new(self, guild_id)
1326    }
1327
1328    /// Get the guild's welcome screen.
1329    ///
1330    /// If the welcome screen is not enabled, this requires the [`MANAGE_GUILD`]
1331    /// permission.
1332    ///
1333    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
1334    pub const fn guild_welcome_screen(
1335        &self,
1336        guild_id: Id<GuildMarker>,
1337    ) -> GetGuildWelcomeScreen<'_> {
1338        GetGuildWelcomeScreen::new(self, guild_id)
1339    }
1340
1341    /// Update the guild's welcome screen.
1342    ///
1343    /// Requires the [`MANAGE_GUILD`] permission.
1344    ///
1345    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
1346    pub const fn update_guild_welcome_screen(
1347        &self,
1348        guild_id: Id<GuildMarker>,
1349    ) -> UpdateGuildWelcomeScreen<'_> {
1350        UpdateGuildWelcomeScreen::new(self, guild_id)
1351    }
1352
1353    /// Get information about an invite by its code.
1354    ///
1355    /// If [`with_counts`] is called, the returned invite will contain
1356    /// approximate member counts.  If [`with_expiration`] is called, it will
1357    /// contain the expiration date.
1358    ///
1359    /// # Examples
1360    ///
1361    /// ```no_run
1362    /// # use twilight_http::Client;
1363    /// #
1364    /// # #[tokio::main]
1365    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
1366    /// # let client = Client::new("my token".to_owned());
1367    /// #
1368    /// let invite = client.invite("code").with_counts().await?;
1369    /// # Ok(()) }
1370    /// ```
1371    ///
1372    /// [`with_counts`]: crate::request::channel::invite::GetInvite::with_counts
1373    /// [`with_expiration`]: crate::request::channel::invite::GetInvite::with_expiration
1374    pub const fn invite<'a>(&'a self, code: &'a str) -> GetInvite<'a> {
1375        GetInvite::new(self, code)
1376    }
1377
1378    /// Create an invite, with options.
1379    ///
1380    /// Requires the [`CREATE_INVITE`] permission.
1381    ///
1382    /// # Examples
1383    ///
1384    /// ```no_run
1385    /// # use twilight_http::Client;
1386    /// # use twilight_model::id::Id;
1387    /// #
1388    /// # #[tokio::main]
1389    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
1390    /// # let client = Client::new("my token".to_owned());
1391    /// #
1392    /// let channel_id = Id::new(123);
1393    /// let invite = client.create_invite(channel_id).max_uses(3).await?;
1394    /// # Ok(()) }
1395    /// ```
1396    ///
1397    /// [`CREATE_INVITE`]: twilight_model::guild::Permissions::CREATE_INVITE
1398    pub const fn create_invite(&self, channel_id: Id<ChannelMarker>) -> CreateInvite<'_> {
1399        CreateInvite::new(self, channel_id)
1400    }
1401
1402    /// Delete an invite by its code.
1403    ///
1404    /// Requires the [`MANAGE_CHANNELS`] permission on the channel this invite
1405    /// belongs to, or [`MANAGE_GUILD`] to remove any invite across the guild.
1406    ///
1407    /// [`MANAGE_CHANNELS`]: twilight_model::guild::Permissions::MANAGE_CHANNELS
1408    /// [`MANAGE_GUILD`]: twilight_model::guild::Permissions::MANAGE_GUILD
1409    pub const fn delete_invite<'a>(&'a self, code: &'a str) -> DeleteInvite<'a> {
1410        DeleteInvite::new(self, code)
1411    }
1412
1413    /// Get a message by [`Id<ChannelMarker>`] and [`Id<MessageMarker>`].
1414    pub const fn message(
1415        &self,
1416        channel_id: Id<ChannelMarker>,
1417        message_id: Id<MessageMarker>,
1418    ) -> GetMessage<'_> {
1419        GetMessage::new(self, channel_id, message_id)
1420    }
1421
1422    /// Send a message to a channel.
1423    ///
1424    /// The message must include at least one of [`attachments`],
1425    /// [`components`], [`content`], [`embeds`], or [`sticker_ids`].
1426    ///
1427    /// # Example
1428    ///
1429    /// ```no_run
1430    /// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
1431    /// use twilight_http::Client;
1432    /// use twilight_model::id::Id;
1433    ///
1434    /// let client = Client::new("my token".to_owned());
1435    ///
1436    /// let channel_id = Id::new(123);
1437    /// let message = client
1438    ///     .create_message(channel_id)
1439    ///     .content("Twilight is best pony")
1440    ///     .tts(true)
1441    ///     .await?;
1442    /// # Ok(()) }
1443    /// ```
1444    ///
1445    /// [`attachments`]: CreateMessage::attachments
1446    /// [`components`]: CreateMessage::components
1447    /// [`content`]: CreateMessage::content
1448    /// [`embeds`]: CreateMessage::embeds
1449    /// [`sticker_ids`]: CreateMessage::sticker_ids
1450    pub const fn create_message(&self, channel_id: Id<ChannelMarker>) -> CreateMessage<'_> {
1451        CreateMessage::new(self, channel_id)
1452    }
1453
1454    /// Delete a message by [`Id<ChannelMarker>`] and [`Id<MessageMarker>`].
1455    pub const fn delete_message(
1456        &self,
1457        channel_id: Id<ChannelMarker>,
1458        message_id: Id<MessageMarker>,
1459    ) -> DeleteMessage<'_> {
1460        DeleteMessage::new(self, channel_id, message_id)
1461    }
1462
1463    /// Delete messages by [`Id<ChannelMarker>`] and Vec<[`Id<MessageMarker>`]>.
1464    ///
1465    /// The vec count can be between 2 and 100. If the supplied
1466    /// [`Id<MessageMarker>`]s are invalid, they still count towards the lower
1467    /// and upper limits. This method will not delete messages older than two
1468    /// weeks. See [Discord Docs/Bulk Delete Messages].
1469    ///
1470    /// # Errors
1471    ///
1472    /// Returns an error of type
1473    /// [`ChannelValidationErrorType::BulkDeleteMessagesInvalid`] when the number of
1474    /// messages to delete in bulk is invalid.
1475    ///
1476    /// [Discord Docs/Bulk Delete Messages]: https://discord.com/developers/docs/resources/channel#bulk-delete-messages
1477    /// [`ChannelValidationErrorType::BulkDeleteMessagesInvalid`]: twilight_validate::channel::ChannelValidationErrorType::BulkDeleteMessagesInvalid
1478    pub fn delete_messages<'a>(
1479        &'a self,
1480        channel_id: Id<ChannelMarker>,
1481        message_ids: &'a [Id<MessageMarker>],
1482    ) -> DeleteMessages<'a> {
1483        DeleteMessages::new(self, channel_id, message_ids)
1484    }
1485
1486    /// Update a message by [`Id<ChannelMarker>`] and [`Id<MessageMarker>`].
1487    ///
1488    /// You can pass [`None`] to any of the methods to remove the associated
1489    /// field. Pass [`None`] to [`content`] to remove the content. You must
1490    /// ensure that the message still contains at least one of [`attachments`],
1491    /// [`components`], [`content`], [`embeds`], or stickers.
1492    ///
1493    /// # Examples
1494    ///
1495    /// Replace the content with `"test update"`:
1496    ///
1497    /// ```no_run
1498    /// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
1499    /// use twilight_http::Client;
1500    /// use twilight_model::id::Id;
1501    ///
1502    /// let client = Client::new("my token".to_owned());
1503    /// client
1504    ///     .update_message(Id::new(1), Id::new(2))
1505    ///     .content(Some("test update"))
1506    ///     .await?;
1507    /// # Ok(()) }
1508    /// ```
1509    ///
1510    /// Remove the message's content:
1511    ///
1512    /// ```no_run
1513    /// # use twilight_http::Client;
1514    /// # use twilight_model::id::Id;
1515    /// #
1516    /// # #[tokio::main]
1517    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
1518    /// # let client = Client::new("my token".to_owned());
1519    /// client
1520    ///     .update_message(Id::new(1), Id::new(2))
1521    ///     .content(None)
1522    ///     .await?;
1523    /// # Ok(()) }
1524    /// ```
1525    ///
1526    /// [`attachments`]: UpdateMessage::attachments
1527    /// [`components`]: UpdateMessage::components
1528    /// [`content`]: UpdateMessage::content
1529    /// [`embeds`]: UpdateMessage::embeds
1530    pub const fn update_message(
1531        &self,
1532        channel_id: Id<ChannelMarker>,
1533        message_id: Id<MessageMarker>,
1534    ) -> UpdateMessage<'_> {
1535        UpdateMessage::new(self, channel_id, message_id)
1536    }
1537
1538    /// Crosspost a message by [`Id<ChannelMarker>`] and [`Id<MessageMarker>`].
1539    pub const fn crosspost_message(
1540        &self,
1541        channel_id: Id<ChannelMarker>,
1542        message_id: Id<MessageMarker>,
1543    ) -> CrosspostMessage<'_> {
1544        CrosspostMessage::new(self, channel_id, message_id)
1545    }
1546
1547    /// Get the pins of a channel.
1548    pub const fn pins(&self, channel_id: Id<ChannelMarker>) -> GetPins<'_> {
1549        GetPins::new(self, channel_id)
1550    }
1551
1552    /// Create a new pin in a channel, by ID.
1553    pub const fn create_pin(
1554        &self,
1555        channel_id: Id<ChannelMarker>,
1556        message_id: Id<MessageMarker>,
1557    ) -> CreatePin<'_> {
1558        CreatePin::new(self, channel_id, message_id)
1559    }
1560
1561    /// Delete a pin in a channel, by ID.
1562    pub const fn delete_pin(
1563        &self,
1564        channel_id: Id<ChannelMarker>,
1565        message_id: Id<MessageMarker>,
1566    ) -> DeletePin<'_> {
1567        DeletePin::new(self, channel_id, message_id)
1568    }
1569
1570    /// Get a list of users that reacted to a message with an `emoji`.
1571    ///
1572    /// This endpoint is limited to 100 users maximum, so if a message has more than 100 reactions,
1573    /// requests must be chained until all reactions are retrieved.
1574    pub const fn reactions<'a>(
1575        &'a self,
1576        channel_id: Id<ChannelMarker>,
1577        message_id: Id<MessageMarker>,
1578        emoji: &'a RequestReactionType<'a>,
1579    ) -> GetReactions<'a> {
1580        GetReactions::new(self, channel_id, message_id, emoji)
1581    }
1582
1583    /// Create a reaction in a [`Id<ChannelMarker>`] on a [`Id<MessageMarker>`].
1584    ///
1585    /// The reaction must be a variant of [`RequestReactionType`].
1586    ///
1587    /// # Examples
1588    /// ```no_run
1589    /// # use twilight_http::{Client, request::channel::reaction::RequestReactionType};
1590    /// # use twilight_model::id::Id;
1591    /// #
1592    /// # #[tokio::main]
1593    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
1594    /// # let client = Client::new("my token".to_owned());
1595    /// #
1596    /// let channel_id = Id::new(123);
1597    /// let message_id = Id::new(456);
1598    /// let emoji = RequestReactionType::Unicode { name: "🌃" };
1599    ///
1600    /// let reaction = client
1601    ///     .create_reaction(channel_id, message_id, &emoji)
1602    ///     .await?;
1603    /// # Ok(()) }
1604    /// ```
1605    pub const fn create_reaction<'a>(
1606        &'a self,
1607        channel_id: Id<ChannelMarker>,
1608        message_id: Id<MessageMarker>,
1609        emoji: &'a RequestReactionType<'a>,
1610    ) -> CreateReaction<'a> {
1611        CreateReaction::new(self, channel_id, message_id, emoji)
1612    }
1613
1614    /// Delete the current user's (`@me`) reaction on a message.
1615    pub const fn delete_current_user_reaction<'a>(
1616        &'a self,
1617        channel_id: Id<ChannelMarker>,
1618        message_id: Id<MessageMarker>,
1619        emoji: &'a RequestReactionType<'a>,
1620    ) -> DeleteReaction<'a> {
1621        DeleteReaction::new(self, channel_id, message_id, emoji, TargetUser::Current)
1622    }
1623
1624    /// Delete a reaction by a user on a message.
1625    pub const fn delete_reaction<'a>(
1626        &'a self,
1627        channel_id: Id<ChannelMarker>,
1628        message_id: Id<MessageMarker>,
1629        emoji: &'a RequestReactionType<'a>,
1630        user_id: Id<UserMarker>,
1631    ) -> DeleteReaction<'a> {
1632        DeleteReaction::new(self, channel_id, message_id, emoji, TargetUser::Id(user_id))
1633    }
1634
1635    /// Remove all reactions on a message of an emoji.
1636    pub const fn delete_all_reaction<'a>(
1637        &'a self,
1638        channel_id: Id<ChannelMarker>,
1639        message_id: Id<MessageMarker>,
1640        emoji: &'a RequestReactionType<'a>,
1641    ) -> DeleteAllReaction<'a> {
1642        DeleteAllReaction::new(self, channel_id, message_id, emoji)
1643    }
1644
1645    /// Delete all reactions by all users on a message.
1646    pub const fn delete_all_reactions(
1647        &self,
1648        channel_id: Id<ChannelMarker>,
1649        message_id: Id<MessageMarker>,
1650    ) -> DeleteAllReactions<'_> {
1651        DeleteAllReactions::new(self, channel_id, message_id)
1652    }
1653
1654    /// Fire a Typing Start event in the channel.
1655    pub const fn create_typing_trigger(
1656        &self,
1657        channel_id: Id<ChannelMarker>,
1658    ) -> CreateTypingTrigger<'_> {
1659        CreateTypingTrigger::new(self, channel_id)
1660    }
1661
1662    /// Create a DM channel with a user.
1663    pub const fn create_private_channel(
1664        &self,
1665        recipient_id: Id<UserMarker>,
1666    ) -> CreatePrivateChannel<'_> {
1667        CreatePrivateChannel::new(self, recipient_id)
1668    }
1669
1670    /// Get the roles of a guild.
1671    pub const fn roles(&self, guild_id: Id<GuildMarker>) -> GetGuildRoles<'_> {
1672        GetGuildRoles::new(self, guild_id)
1673    }
1674
1675    /// Get the role member counts of a guild.
1676    pub const fn role_member_counts(
1677        &self,
1678        guild_id: Id<GuildMarker>,
1679    ) -> GetGuildRoleMemberCounts<'_> {
1680        GetGuildRoleMemberCounts::new(self, guild_id)
1681    }
1682
1683    /// Get a role of a guild.
1684    pub const fn role(&self, guild_id: Id<GuildMarker>, role_id: Id<RoleMarker>) -> GetRole<'_> {
1685        GetRole::new(self, guild_id, role_id)
1686    }
1687
1688    /// Create a role in a guild.
1689    ///
1690    /// # Examples
1691    ///
1692    /// ```no_run
1693    /// # use twilight_http::Client;
1694    /// use twilight_model::id::Id;
1695    ///
1696    /// # #[tokio::main]
1697    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
1698    /// # let client = Client::new("my token".to_owned());
1699    /// let guild_id = Id::new(234);
1700    ///
1701    /// client
1702    ///     .create_role(guild_id)
1703    ///     .color(0xd90083)
1704    ///     .name("Bright Pink")
1705    ///     .await?;
1706    /// # Ok(()) }
1707    /// ```
1708    pub const fn create_role(&self, guild_id: Id<GuildMarker>) -> CreateRole<'_> {
1709        CreateRole::new(self, guild_id)
1710    }
1711
1712    /// Delete a role in a guild, by id.
1713    pub const fn delete_role(
1714        &self,
1715        guild_id: Id<GuildMarker>,
1716        role_id: Id<RoleMarker>,
1717    ) -> DeleteRole<'_> {
1718        DeleteRole::new(self, guild_id, role_id)
1719    }
1720
1721    /// Update a role by guild id and its id.
1722    pub const fn update_role(
1723        &self,
1724        guild_id: Id<GuildMarker>,
1725        role_id: Id<RoleMarker>,
1726    ) -> UpdateRole<'_> {
1727        UpdateRole::new(self, guild_id, role_id)
1728    }
1729
1730    /// Modify the position of the roles.
1731    ///
1732    /// The minimum amount of roles to modify, is a swap between two roles.
1733    pub const fn update_role_positions<'a>(
1734        &'a self,
1735        guild_id: Id<GuildMarker>,
1736        roles: &'a [RolePosition],
1737    ) -> UpdateRolePositions<'a> {
1738        UpdateRolePositions::new(self, guild_id, roles)
1739    }
1740
1741    /// Create a new stage instance associated with a stage channel.
1742    ///
1743    /// Requires the user to be a moderator of the stage channel.
1744    ///
1745    /// # Errors
1746    ///
1747    /// Returns an error of type [`ValidationError::StageTopic`] when the topic
1748    /// is not between 1 and 120 characters in length.
1749    ///
1750    /// [`ValidationError::StageTopic`]: twilight_validate::request::ValidationErrorType::StageTopic
1751    pub fn create_stage_instance<'a>(
1752        &'a self,
1753        channel_id: Id<ChannelMarker>,
1754        topic: &'a str,
1755    ) -> CreateStageInstance<'a> {
1756        CreateStageInstance::new(self, channel_id, topic)
1757    }
1758
1759    /// Gets the stage instance associated with a stage channel, if it exists.
1760    pub const fn stage_instance(&self, channel_id: Id<ChannelMarker>) -> GetStageInstance<'_> {
1761        GetStageInstance::new(self, channel_id)
1762    }
1763
1764    /// Update fields of an existing stage instance.
1765    ///
1766    /// Requires the user to be a moderator of the stage channel.
1767    pub const fn update_stage_instance(
1768        &self,
1769        channel_id: Id<ChannelMarker>,
1770    ) -> UpdateStageInstance<'_> {
1771        UpdateStageInstance::new(self, channel_id)
1772    }
1773
1774    /// Delete the stage instance of a stage channel.
1775    ///
1776    /// Requires the user to be a moderator of the stage channel.
1777    pub const fn delete_stage_instance(
1778        &self,
1779        channel_id: Id<ChannelMarker>,
1780    ) -> DeleteStageInstance<'_> {
1781        DeleteStageInstance::new(self, channel_id)
1782    }
1783
1784    /// Create a new guild based on a template.
1785    ///
1786    /// This endpoint can only be used by bots in less than 10 guilds.
1787    ///
1788    /// # Errors
1789    ///
1790    /// Returns an error of type [`ValidationErrorType::TemplateName`] if the
1791    /// name is invalid.
1792    ///
1793    /// [`ValidationErrorType::TemplateName`]: twilight_validate::request::ValidationErrorType::TemplateName
1794    pub fn create_guild_from_template<'a>(
1795        &'a self,
1796        template_code: &'a str,
1797        name: &'a str,
1798    ) -> CreateGuildFromTemplate<'a> {
1799        CreateGuildFromTemplate::new(self, template_code, name)
1800    }
1801
1802    /// Create a template from the current state of the guild.
1803    ///
1804    /// Requires the `MANAGE_GUILD` permission. The name must be at least 1 and
1805    /// at most 100 characters in length.
1806    ///
1807    /// # Errors
1808    ///
1809    /// Returns an error of type [`ValidationErrorType::TemplateName`] if the
1810    /// name is invalid.
1811    ///
1812    /// [`ValidationErrorType::TemplateName`]: twilight_validate::request::ValidationErrorType::TemplateName
1813    pub fn create_template<'a>(
1814        &'a self,
1815        guild_id: Id<GuildMarker>,
1816        name: &'a str,
1817    ) -> CreateTemplate<'a> {
1818        CreateTemplate::new(self, guild_id, name)
1819    }
1820
1821    /// Delete a template by ID and code.
1822    pub const fn delete_template<'a>(
1823        &'a self,
1824        guild_id: Id<GuildMarker>,
1825        template_code: &'a str,
1826    ) -> DeleteTemplate<'a> {
1827        DeleteTemplate::new(self, guild_id, template_code)
1828    }
1829
1830    /// Get a template by its code.
1831    pub const fn get_template<'a>(&'a self, template_code: &'a str) -> GetTemplate<'a> {
1832        GetTemplate::new(self, template_code)
1833    }
1834
1835    /// Get a list of templates in a guild, by ID.
1836    pub const fn get_templates(&self, guild_id: Id<GuildMarker>) -> GetTemplates<'_> {
1837        GetTemplates::new(self, guild_id)
1838    }
1839
1840    /// Sync a template to the current state of the guild, by ID and code.
1841    pub const fn sync_template<'a>(
1842        &'a self,
1843        guild_id: Id<GuildMarker>,
1844        template_code: &'a str,
1845    ) -> SyncTemplate<'a> {
1846        SyncTemplate::new(self, guild_id, template_code)
1847    }
1848
1849    /// Update the template's metadata, by ID and code.
1850    pub const fn update_template<'a>(
1851        &'a self,
1852        guild_id: Id<GuildMarker>,
1853        template_code: &'a str,
1854    ) -> UpdateTemplate<'a> {
1855        UpdateTemplate::new(self, guild_id, template_code)
1856    }
1857
1858    /// Returns all active threads in the guild.
1859    ///
1860    /// Includes public and private threads. Threads are ordered by their ID in
1861    /// descending order.
1862    ///
1863    /// # Examples
1864    ///
1865    /// ```no_run
1866    /// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
1867    /// use twilight_http::Client;
1868    /// use twilight_model::id::Id;
1869    ///
1870    /// let client = Client::new("my token".to_owned());
1871    /// let guild_id = Id::new(234);
1872    ///
1873    /// let threads = client.active_threads(guild_id).await?.model().await?;
1874    /// # Ok(()) }
1875    /// ```
1876    pub const fn active_threads(&self, guild_id: Id<GuildMarker>) -> GetActiveThreads<'_> {
1877        GetActiveThreads::new(self, guild_id)
1878    }
1879
1880    /// Add another member to a thread.
1881    ///
1882    /// Requires the ability to send messages in the thread, and that the thread
1883    /// is not archived.
1884    pub const fn add_thread_member(
1885        &self,
1886        channel_id: Id<ChannelMarker>,
1887        user_id: Id<UserMarker>,
1888    ) -> AddThreadMember<'_> {
1889        AddThreadMember::new(self, channel_id, user_id)
1890    }
1891
1892    /// Start a thread in a forum channel.
1893    pub const fn create_forum_thread<'a>(
1894        &'a self,
1895        channel_id: Id<ChannelMarker>,
1896        name: &'a str,
1897    ) -> CreateForumThread<'a> {
1898        CreateForumThread::new(self, channel_id, name)
1899    }
1900
1901    /// Start a thread that is not connected to a message.
1902    ///
1903    /// Automatic archive durations are not locked behind the guild's boost
1904    /// level.
1905    ///
1906    /// To make a [`PrivateThread`], the guild must also have the
1907    /// `PRIVATE_THREADS` feature.
1908    ///
1909    /// # Errors
1910    ///
1911    /// Returns an error of type [`NameInvalid`] if the channel's name's length is
1912    /// incorrect.
1913    ///
1914    /// Returns an error of type [`TypeInvalid`] if the channel is not a thread.
1915    ///
1916    /// [`NameInvalid`]: twilight_validate::channel::ChannelValidationErrorType::NameInvalid
1917    /// [`PrivateThread`]: twilight_model::channel::ChannelType::PrivateThread
1918    /// [`TypeInvalid`]: twilight_validate::channel::ChannelValidationErrorType::TypeInvalid
1919    pub fn create_thread<'a>(
1920        &'a self,
1921        channel_id: Id<ChannelMarker>,
1922        name: &'a str,
1923        kind: ChannelType,
1924    ) -> CreateThread<'a> {
1925        CreateThread::new(self, channel_id, name, kind)
1926    }
1927
1928    /// Create a new thread from an existing message.
1929    ///
1930    /// When called on a [`GuildText`] channel, this creates a
1931    /// [`PublicThread`].
1932    ///
1933    /// When called on a [`GuildAnnouncement`] channel, this creates a
1934    /// [`AnnouncementThread`].
1935    ///
1936    /// Automatic archive durations are not locked behind the guild's boost
1937    /// level.
1938    ///
1939    /// The thread's ID will be the same as its parent message. This ensures
1940    /// only one thread can be created per message.
1941    ///
1942    /// # Errors
1943    ///
1944    /// Returns an error of type [`NameInvalid`] if the channel's name's length is
1945    /// incorrect.
1946    ///
1947    /// Returns an error of type [`TypeInvalid`] if the channel is not a thread.
1948    ///
1949    /// [`AnnouncementThread`]: twilight_model::channel::ChannelType::AnnouncementThread
1950    /// [`GuildAnnouncement`]: twilight_model::channel::ChannelType::GuildAnnouncement
1951    /// [`GuildText`]: twilight_model::channel::ChannelType::GuildText
1952    /// [`NameInvalid`]: twilight_validate::channel::ChannelValidationErrorType::NameInvalid
1953    /// [`PublicThread`]: twilight_model::channel::ChannelType::PublicThread
1954    /// [`TypeInvalid`]: twilight_validate::channel::ChannelValidationErrorType::TypeInvalid
1955    pub fn create_thread_from_message<'a>(
1956        &'a self,
1957        channel_id: Id<ChannelMarker>,
1958        message_id: Id<MessageMarker>,
1959        name: &'a str,
1960    ) -> CreateThreadFromMessage<'a> {
1961        CreateThreadFromMessage::new(self, channel_id, message_id, name)
1962    }
1963
1964    /// Add the current user to a thread.
1965    pub const fn join_thread(&self, channel_id: Id<ChannelMarker>) -> JoinThread<'_> {
1966        JoinThread::new(self, channel_id)
1967    }
1968
1969    /// Returns archived private threads in the channel that the current user
1970    /// has joined.
1971    ///
1972    /// Threads are ordered by their ID in descending order.
1973    pub const fn joined_private_archived_threads(
1974        &self,
1975        channel_id: Id<ChannelMarker>,
1976    ) -> GetJoinedPrivateArchivedThreads<'_> {
1977        GetJoinedPrivateArchivedThreads::new(self, channel_id)
1978    }
1979
1980    /// Remove the current user from a thread.
1981    ///
1982    /// Requires that the thread is not archived.
1983    pub const fn leave_thread(&self, channel_id: Id<ChannelMarker>) -> LeaveThread<'_> {
1984        LeaveThread::new(self, channel_id)
1985    }
1986
1987    /// Returns archived private threads in the channel.
1988    ///
1989    /// Requires both [`READ_MESSAGE_HISTORY`] and [`MANAGE_THREADS`].
1990    ///
1991    /// [`MANAGE_THREADS`]: twilight_model::guild::Permissions::MANAGE_THREADS
1992    /// [`READ_MESSAGE_HISTORY`]: twilight_model::guild::Permissions::READ_MESSAGE_HISTORY
1993    pub const fn private_archived_threads(
1994        &self,
1995        channel_id: Id<ChannelMarker>,
1996    ) -> GetPrivateArchivedThreads<'_> {
1997        GetPrivateArchivedThreads::new(self, channel_id)
1998    }
1999
2000    /// Returns archived public threads in the channel.
2001    ///
2002    /// Requires the [`READ_MESSAGE_HISTORY`] permission.
2003    ///
2004    /// Threads are ordered by [`archive_timestamp`] in descending order.
2005    ///
2006    /// When called in a [`GuildText`] channel, returns [`PublicThread`]s.
2007    ///
2008    /// When called in a [`GuildAnnouncement`] channel, returns [`AnnouncementThread`]s.
2009    ///
2010    /// [`AnnouncementThread`]: twilight_model::channel::ChannelType::AnnouncementThread
2011    /// [`archive_timestamp`]: twilight_model::channel::thread::ThreadMetadata::archive_timestamp
2012    /// [`GuildAnnouncement`]: twilight_model::channel::ChannelType::GuildAnnouncement
2013    /// [`GuildText`]: twilight_model::channel::ChannelType::GuildText
2014    /// [`PublicThread`]: twilight_model::channel::ChannelType::PublicThread
2015    /// [`READ_MESSAGE_HISTORY`]: twilight_model::guild::Permissions::READ_MESSAGE_HISTORY
2016    pub const fn public_archived_threads(
2017        &self,
2018        channel_id: Id<ChannelMarker>,
2019    ) -> GetPublicArchivedThreads<'_> {
2020        GetPublicArchivedThreads::new(self, channel_id)
2021    }
2022
2023    /// Remove another member from a thread.
2024    ///
2025    /// Requires that the thread is not archived.
2026    ///
2027    /// Requires the [`MANAGE_THREADS`] permission, unless both the thread is a
2028    /// [`PrivateThread`], and the current user is the creator of the
2029    /// thread.
2030    ///
2031    /// [`MANAGE_THREADS`]: twilight_model::guild::Permissions::MANAGE_THREADS
2032    /// [`PrivateThread`]: twilight_model::channel::ChannelType::PrivateThread
2033    pub const fn remove_thread_member(
2034        &self,
2035        channel_id: Id<ChannelMarker>,
2036        user_id: Id<UserMarker>,
2037    ) -> RemoveThreadMember<'_> {
2038        RemoveThreadMember::new(self, channel_id, user_id)
2039    }
2040
2041    /// Returns a [`ThreadMember`] in a thread.
2042    ///
2043    /// [`ThreadMember`]: twilight_model::channel::thread::ThreadMember
2044    pub const fn thread_member(
2045        &self,
2046        channel_id: Id<ChannelMarker>,
2047        user_id: Id<UserMarker>,
2048    ) -> GetThreadMember<'_> {
2049        GetThreadMember::new(self, channel_id, user_id)
2050    }
2051
2052    /// Returns the [`ThreadMember`]s of the thread.
2053    ///
2054    /// [`ThreadMember`]: twilight_model::channel::thread::ThreadMember
2055    pub const fn thread_members(&self, channel_id: Id<ChannelMarker>) -> GetThreadMembers<'_> {
2056        GetThreadMembers::new(self, channel_id)
2057    }
2058
2059    /// Update a thread.
2060    ///
2061    /// All fields are optional. The minimum length of the name is 1 UTF-16
2062    /// characters and the maximum is 100 UTF-16 characters.
2063    pub const fn update_thread(&self, channel_id: Id<ChannelMarker>) -> UpdateThread<'_> {
2064        UpdateThread::new(self, channel_id)
2065    }
2066
2067    /// Get a user's information by id.
2068    pub const fn user(&self, user_id: Id<UserMarker>) -> GetUser<'_> {
2069        GetUser::new(self, user_id)
2070    }
2071
2072    /// Get voice state of a user in a guild.
2073    ///
2074    /// # Caveats
2075    ///
2076    /// - User must already have joined a voice/stage channel in this guild.
2077    pub const fn user_voice_state(
2078        &self,
2079        guild_id: Id<GuildMarker>,
2080        user_id: Id<UserMarker>,
2081    ) -> GetUserVoiceState<'_> {
2082        GetUserVoiceState::new(self, guild_id, user_id)
2083    }
2084
2085    /// Update another user's voice state.
2086    ///
2087    /// # Caveats
2088    ///
2089    /// - `channel_id` must currently point to a stage channel.
2090    /// - User must already have joined `channel_id`.
2091    pub const fn update_user_voice_state(
2092        &self,
2093        guild_id: Id<GuildMarker>,
2094        user_id: Id<UserMarker>,
2095        channel_id: Id<ChannelMarker>,
2096    ) -> UpdateUserVoiceState<'_> {
2097        UpdateUserVoiceState::new(self, guild_id, user_id, channel_id)
2098    }
2099
2100    /// Get a list of voice regions that can be used when creating a guild.
2101    pub const fn voice_regions(&self) -> GetVoiceRegions<'_> {
2102        GetVoiceRegions::new(self)
2103    }
2104
2105    /// Get a webhook by ID.
2106    pub const fn webhook(&self, id: Id<WebhookMarker>) -> GetWebhook<'_> {
2107        GetWebhook::new(self, id)
2108    }
2109
2110    /// Create a webhook in a channel.
2111    ///
2112    /// # Examples
2113    ///
2114    /// ```no_run
2115    /// # use twilight_http::Client;
2116    /// # use twilight_model::id::Id;
2117    /// #
2118    /// # #[tokio::main]
2119    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2120    /// # let client = Client::new("my token".to_owned());
2121    /// let channel_id = Id::new(123);
2122    ///
2123    /// let webhook = client.create_webhook(channel_id, "Twily Bot").await?;
2124    /// # Ok(()) }
2125    /// ```
2126    ///
2127    /// # Errors
2128    ///
2129    /// Returns an error of type [`WebhookUsername`] if the webhook's name is
2130    /// invalid.
2131    ///
2132    /// [`WebhookUsername`]: twilight_validate::request::ValidationErrorType::WebhookUsername
2133    pub fn create_webhook<'a>(
2134        &'a self,
2135        channel_id: Id<ChannelMarker>,
2136        name: &'a str,
2137    ) -> CreateWebhook<'a> {
2138        CreateWebhook::new(self, channel_id, name)
2139    }
2140
2141    /// Delete a webhook by its ID.
2142    pub const fn delete_webhook(&self, id: Id<WebhookMarker>) -> DeleteWebhook<'_> {
2143        DeleteWebhook::new(self, id)
2144    }
2145
2146    /// Update a webhook by ID.
2147    pub const fn update_webhook(&self, webhook_id: Id<WebhookMarker>) -> UpdateWebhook<'_> {
2148        UpdateWebhook::new(self, webhook_id)
2149    }
2150
2151    /// Update a webhook, with a token, by ID.
2152    pub const fn update_webhook_with_token<'a>(
2153        &'a self,
2154        webhook_id: Id<WebhookMarker>,
2155        token: &'a str,
2156    ) -> UpdateWebhookWithToken<'a> {
2157        UpdateWebhookWithToken::new(self, webhook_id, token)
2158    }
2159
2160    /// Execute a webhook, sending a message to its channel.
2161    ///
2162    /// The message must include at least one of [`attachments`], [`components`]
2163    /// [`content`], or [`embeds`].
2164    ///
2165    /// # Examples
2166    ///
2167    /// ```no_run
2168    /// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
2169    /// use twilight_http::Client;
2170    /// use twilight_model::id::Id;
2171    ///
2172    /// let client = Client::new("my token".to_owned());
2173    /// let id = Id::new(432);
2174    ///
2175    /// let webhook = client
2176    ///     .execute_webhook(id, "webhook token")
2177    ///     .content("Pinkie...")
2178    ///     .await?;
2179    /// # Ok(()) }
2180    /// ```
2181    ///
2182    /// [`attachments`]: ExecuteWebhook::attachments
2183    /// [`components`]: ExecuteWebhook::components
2184    /// [`content`]: ExecuteWebhook::content
2185    /// [`embeds`]: ExecuteWebhook::embeds
2186    pub const fn execute_webhook<'a>(
2187        &'a self,
2188        webhook_id: Id<WebhookMarker>,
2189        token: &'a str,
2190    ) -> ExecuteWebhook<'a> {
2191        ExecuteWebhook::new(self, webhook_id, token)
2192    }
2193
2194    /// Get a webhook message by webhook ID, token, and message ID.
2195    pub const fn webhook_message<'a>(
2196        &'a self,
2197        webhook_id: Id<WebhookMarker>,
2198        token: &'a str,
2199        message_id: Id<MessageMarker>,
2200    ) -> GetWebhookMessage<'a> {
2201        GetWebhookMessage::new(self, webhook_id, token, message_id)
2202    }
2203
2204    /// Update a message executed by a webhook.
2205    ///
2206    /// You can pass [`None`] to any of the methods to remove the associated
2207    /// field. Pass [`None`] to [`content`] to remove the content. You must
2208    /// ensure that the message still contains at least one of [`attachments`],
2209    /// [`components`], [`content`], or [`embeds`].
2210    ///
2211    /// # Examples
2212    ///
2213    /// ```no_run
2214    /// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
2215    /// use twilight_http::Client;
2216    /// use twilight_model::id::Id;
2217    ///
2218    /// let client = Client::new("token".to_owned());
2219    /// client
2220    ///     .update_webhook_message(Id::new(1), "token here", Id::new(2))
2221    ///     .content(Some("new message content"))
2222    ///     .await?;
2223    /// # Ok(()) }
2224    /// ```
2225    ///
2226    /// [`attachments`]: UpdateWebhookMessage::attachments
2227    /// [`components`]: UpdateWebhookMessage::components
2228    /// [`content`]: UpdateWebhookMessage::content
2229    /// [`embeds`]: UpdateWebhookMessage::embeds
2230    pub const fn update_webhook_message<'a>(
2231        &'a self,
2232        webhook_id: Id<WebhookMarker>,
2233        token: &'a str,
2234        message_id: Id<MessageMarker>,
2235    ) -> UpdateWebhookMessage<'a> {
2236        UpdateWebhookMessage::new(self, webhook_id, token, message_id)
2237    }
2238
2239    /// Delete a message executed by a webhook.
2240    ///
2241    /// # Examples
2242    ///
2243    /// ```no_run
2244    /// # use twilight_http::Client;
2245    /// use twilight_model::id::Id;
2246    ///
2247    /// # #[tokio::main]
2248    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2249    /// # let client = Client::new("token".to_owned());
2250    /// client
2251    ///     .delete_webhook_message(Id::new(1), "token here", Id::new(2))
2252    ///     .await?;
2253    /// # Ok(()) }
2254    /// ```
2255    pub const fn delete_webhook_message<'a>(
2256        &'a self,
2257        webhook_id: Id<WebhookMarker>,
2258        token: &'a str,
2259        message_id: Id<MessageMarker>,
2260    ) -> DeleteWebhookMessage<'a> {
2261        DeleteWebhookMessage::new(self, webhook_id, token, message_id)
2262    }
2263
2264    /// Delete a scheduled event in a guild.
2265    ///
2266    /// # Examples
2267    ///
2268    /// ```no_run
2269    /// # use twilight_http::Client;
2270    /// # use twilight_model::id::Id;
2271    /// # #[tokio::main]
2272    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2273    /// # let client = Client::new("token".to_owned());
2274    /// let guild_id = Id::new(1);
2275    /// let scheduled_event_id = Id::new(2);
2276    ///
2277    /// client
2278    ///     .delete_guild_scheduled_event(guild_id, scheduled_event_id)
2279    ///     .await?;
2280    /// # Ok(()) }
2281    /// ```
2282    pub const fn delete_guild_scheduled_event(
2283        &self,
2284        guild_id: Id<GuildMarker>,
2285        scheduled_event_id: Id<ScheduledEventMarker>,
2286    ) -> DeleteGuildScheduledEvent<'_> {
2287        DeleteGuildScheduledEvent::new(self, guild_id, scheduled_event_id)
2288    }
2289
2290    /// Create a scheduled event in a guild.
2291    ///
2292    /// Once a guild is selected, you must choose one of three event types to
2293    /// create. The request builders will ensure you provide the correct data to
2294    /// Discord. See [Discord Docs/Create Guild Scheduled Event].
2295    ///
2296    /// The name must be between 1 and 100 characters in length. For external
2297    /// events, the location must be between 1 and 100 characters in length.
2298    ///
2299    /// # Examples
2300    ///
2301    /// Create an event in a stage instance:
2302    ///
2303    /// ```no_run
2304    /// # use twilight_http::Client;
2305    /// use twilight_model::{guild::scheduled_event::PrivacyLevel, id::Id, util::Timestamp};
2306    /// # #[tokio::main]
2307    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2308    /// # let client = Client::new("token".to_owned());
2309    /// let guild_id = Id::new(1);
2310    /// let channel_id = Id::new(2);
2311    /// let garfield_start_time = Timestamp::parse("2022-01-01T14:00:00+00:00")?;
2312    ///
2313    /// client
2314    ///     .create_guild_scheduled_event(guild_id, PrivacyLevel::GuildOnly)
2315    ///     .stage_instance(
2316    ///         channel_id,
2317    ///         "Garfield Appreciation Hour",
2318    ///         &garfield_start_time,
2319    ///     )
2320    ///     .description("Discuss: How important is Garfield to You?")
2321    ///     .await?;
2322    /// # Ok(()) }
2323    /// ```
2324    ///
2325    /// Create an external event:
2326    ///
2327    /// ```no_run
2328    /// # use twilight_http::Client;
2329    /// use twilight_model::{guild::scheduled_event::PrivacyLevel, id::Id, util::Timestamp};
2330    /// # #[tokio::main]
2331    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2332    /// # let client = Client::new("token".to_owned());
2333    /// let guild_id = Id::new(1);
2334    /// let garfield_con_start_time = Timestamp::parse("2022-01-04T08:00:00+00:00")?;
2335    /// let garfield_con_end_time = Timestamp::parse("2022-01-06T17:00:00+00:00")?;
2336    ///
2337    /// client
2338    ///     .create_guild_scheduled_event(guild_id, PrivacyLevel::GuildOnly)
2339    ///     .external(
2340    ///         "Garfield Con 2022",
2341    ///         "Baltimore Convention Center",
2342    ///         &garfield_con_start_time,
2343    ///         &garfield_con_end_time,
2344    ///     )
2345    ///     .description(
2346    ///         "In a spiritual successor to BronyCon, Garfield fans from \
2347    /// around the globe celebrate all things related to the loveable cat.",
2348    ///     )
2349    ///     .await?;
2350    /// # Ok(()) }
2351    /// ```
2352    ///
2353    /// [Discord Docs/Create Guild Scheduled Event]: https://discord.com/developers/docs/resources/guild-scheduled-event#create-guild-scheduled-event
2354    pub const fn create_guild_scheduled_event(
2355        &self,
2356        guild_id: Id<GuildMarker>,
2357        privacy_level: PrivacyLevel,
2358    ) -> CreateGuildScheduledEvent<'_> {
2359        CreateGuildScheduledEvent::new(self, guild_id, privacy_level)
2360    }
2361
2362    /// Get a scheduled event in a guild.
2363    pub const fn guild_scheduled_event(
2364        &self,
2365        guild_id: Id<GuildMarker>,
2366        scheduled_event_id: Id<ScheduledEventMarker>,
2367    ) -> GetGuildScheduledEvent<'_> {
2368        GetGuildScheduledEvent::new(self, guild_id, scheduled_event_id)
2369    }
2370
2371    /// Get a list of users subscribed to a scheduled event.
2372    ///
2373    /// Users are returned in ascending order by `user_id`. [`before`] and
2374    /// [`after`] both take a user id. If both are specified, only [`before`] is
2375    /// respected. The default [`limit`] is 100. See
2376    /// [Discord Docs/Get Guild Scheduled Event Users].
2377    ///
2378    /// [`after`]: GetGuildScheduledEventUsers::after
2379    /// [`before`]: GetGuildScheduledEventUsers::before
2380    /// [`limit`]: GetGuildScheduledEventUsers::limit
2381    /// [Discord Docs/Get Guild Scheduled Event Users]: https://discord.com/developers/docs/resources/guild-scheduled-event#get-guild-scheduled-event-users
2382    pub const fn guild_scheduled_event_users(
2383        &self,
2384        guild_id: Id<GuildMarker>,
2385        scheduled_event_id: Id<ScheduledEventMarker>,
2386    ) -> GetGuildScheduledEventUsers<'_> {
2387        GetGuildScheduledEventUsers::new(self, guild_id, scheduled_event_id)
2388    }
2389
2390    /// Get a list of scheduled events in a guild.
2391    pub const fn guild_scheduled_events(
2392        &self,
2393        guild_id: Id<GuildMarker>,
2394    ) -> GetGuildScheduledEvents<'_> {
2395        GetGuildScheduledEvents::new(self, guild_id)
2396    }
2397
2398    /// Update a scheduled event in a guild.
2399    ///
2400    /// This endpoint supports changing the type of event. When changing the
2401    /// entity type to either [`EntityType::StageInstance`] or
2402    /// [`EntityType::Voice`], an [`Id<ChannelMarker>`] must be provided if it
2403    /// does not already exist.
2404    ///
2405    /// When changing the entity type to [`EntityType::External`], the
2406    /// `channel_id` field is cleared and the [`channel_id`] method has no
2407    /// effect. Additionally, you must set a location with [`location`].
2408    ///
2409    /// [`EntityType::External`]: twilight_model::guild::scheduled_event::EntityType::External
2410    /// [`EntityType::StageInstance`]: twilight_model::guild::scheduled_event::EntityType::StageInstance
2411    /// [`EntityType::Voice`]: twilight_model::guild::scheduled_event::EntityType::Voice
2412    /// [`channel_id`]: UpdateGuildScheduledEvent::channel_id
2413    /// [`location`]: UpdateGuildScheduledEvent::location
2414    pub const fn update_guild_scheduled_event(
2415        &self,
2416        guild_id: Id<GuildMarker>,
2417        scheduled_event_id: Id<ScheduledEventMarker>,
2418    ) -> UpdateGuildScheduledEvent<'_> {
2419        UpdateGuildScheduledEvent::new(self, guild_id, scheduled_event_id)
2420    }
2421
2422    /// Returns a single sticker by its ID.
2423    ///
2424    /// # Examples
2425    ///
2426    /// ```no_run
2427    /// use twilight_http::Client;
2428    /// use twilight_model::id::Id;
2429    ///
2430    /// # #[tokio::main]
2431    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2432    /// let client = Client::new("my token".to_owned());
2433    ///
2434    /// let id = Id::new(123);
2435    /// let sticker = client.sticker(id).await?.model().await?;
2436    ///
2437    /// println!("{sticker:#?}");
2438    /// # Ok(()) }
2439    /// ```
2440    pub const fn sticker(&self, sticker_id: Id<StickerMarker>) -> GetSticker<'_> {
2441        GetSticker::new(self, sticker_id)
2442    }
2443
2444    /// Returns a list of sticker packs available to Nitro subscribers.
2445    ///
2446    /// # Examples
2447    ///
2448    /// ```no_run
2449    /// use twilight_http::Client;
2450    ///
2451    /// # #[tokio::main]
2452    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2453    /// let client = Client::new("my token".to_owned());
2454    ///
2455    /// let packs = client.nitro_sticker_packs().await?.model().await?;
2456    ///
2457    /// println!("{}", packs.sticker_packs.len());
2458    /// # Ok(()) }
2459    /// ```
2460    pub const fn nitro_sticker_packs(&self) -> GetNitroStickerPacks<'_> {
2461        GetNitroStickerPacks::new(self)
2462    }
2463
2464    /// Returns a list of stickers in a guild.
2465    ///
2466    /// # Examples
2467    ///
2468    /// ```no_run
2469    /// use twilight_http::Client;
2470    /// use twilight_model::id::Id;
2471    ///
2472    /// # #[tokio::main]
2473    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2474    /// let client = Client::new("my token".to_owned());
2475    ///
2476    /// let guild_id = Id::new(1);
2477    /// let stickers = client.guild_stickers(guild_id).await?.models().await?;
2478    ///
2479    /// println!("{}", stickers.len());
2480    /// # Ok(()) }
2481    /// ```
2482    pub const fn guild_stickers(&self, guild_id: Id<GuildMarker>) -> GetGuildStickers<'_> {
2483        GetGuildStickers::new(self, guild_id)
2484    }
2485
2486    /// Returns a guild sticker by the guild's ID and the sticker's ID.
2487    ///
2488    /// # Examples
2489    ///
2490    /// ```no_run
2491    /// use twilight_http::Client;
2492    /// use twilight_model::id::Id;
2493    ///
2494    /// # #[tokio::main]
2495    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2496    /// let client = Client::new("my token".to_owned());
2497    ///
2498    /// let guild_id = Id::new(1);
2499    /// let sticker_id = Id::new(2);
2500    /// let sticker = client
2501    ///     .guild_sticker(guild_id, sticker_id)
2502    ///     .await?
2503    ///     .model()
2504    ///     .await?;
2505    ///
2506    /// println!("{sticker:#?}");
2507    /// # Ok(()) }
2508    /// ```
2509    pub const fn guild_sticker(
2510        &self,
2511        guild_id: Id<GuildMarker>,
2512        sticker_id: Id<StickerMarker>,
2513    ) -> GetGuildSticker<'_> {
2514        GetGuildSticker::new(self, guild_id, sticker_id)
2515    }
2516
2517    /// Creates a sticker in a guild, and returns the created sticker.
2518    ///
2519    /// # Examples
2520    ///
2521    /// ```no_run
2522    /// use twilight_http::Client;
2523    /// use twilight_model::id::Id;
2524    ///
2525    /// # #[tokio::main]
2526    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2527    /// let client = Client::new("my token".to_owned());
2528    ///
2529    /// let guild_id = Id::new(1);
2530    /// let sticker = client
2531    ///     .create_guild_sticker(
2532    ///         guild_id,
2533    ///         &"sticker name",
2534    ///         &"sticker description",
2535    ///         &"sticker,tags",
2536    ///         &[23, 23, 23, 23],
2537    ///     )
2538    ///     .await?
2539    ///     .model()
2540    ///     .await?;
2541    ///
2542    /// println!("{sticker:#?}");
2543    /// # Ok(()) }
2544    /// ```
2545    ///
2546    /// # Errors
2547    ///
2548    /// Returns an error of type [`DescriptionInvalid`] if the length is invalid.
2549    ///
2550    /// Returns an error of type [`NameInvalid`] if the length is invalid.
2551    ///
2552    /// Returns an error of type [`TagsInvalid`] if the length is invalid.
2553    ///
2554    /// [`DescriptionInvalid`]: twilight_validate::sticker::StickerValidationErrorType::DescriptionInvalid
2555    /// [`NameInvalid`]: twilight_validate::sticker::StickerValidationErrorType::NameInvalid
2556    /// [`TagsInvalid`]: twilight_validate::sticker::StickerValidationErrorType::TagsInvalid
2557    pub fn create_guild_sticker<'a>(
2558        &'a self,
2559        guild_id: Id<GuildMarker>,
2560        name: &'a str,
2561        description: &'a str,
2562        tags: &'a str,
2563        file: &'a [u8],
2564    ) -> CreateGuildSticker<'a> {
2565        CreateGuildSticker::new(self, guild_id, name, description, tags, file)
2566    }
2567
2568    /// Updates a sticker in a guild, and returns the updated sticker.
2569    ///
2570    /// # Examples
2571    ///
2572    /// ```no_run
2573    /// use twilight_http::Client;
2574    /// use twilight_model::id::Id;
2575    ///
2576    /// # #[tokio::main]
2577    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2578    /// let client = Client::new("my token".to_owned());
2579    ///
2580    /// let guild_id = Id::new(1);
2581    /// let sticker_id = Id::new(2);
2582    /// let sticker = client
2583    ///     .update_guild_sticker(guild_id, sticker_id)
2584    ///     .description("new description")
2585    ///     .await?
2586    ///     .model()
2587    ///     .await?;
2588    ///
2589    /// println!("{sticker:#?}");
2590    /// # Ok(()) }
2591    /// ```
2592    pub const fn update_guild_sticker(
2593        &self,
2594        guild_id: Id<GuildMarker>,
2595        sticker_id: Id<StickerMarker>,
2596    ) -> UpdateGuildSticker<'_> {
2597        UpdateGuildSticker::new(self, guild_id, sticker_id)
2598    }
2599
2600    /// Deletes a guild sticker by the ID of the guild and its ID.
2601    ///
2602    /// # Examples
2603    ///
2604    /// ```no_run
2605    /// use twilight_http::Client;
2606    /// use twilight_model::id::Id;
2607    ///
2608    /// # #[tokio::main]
2609    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2610    /// let client = Client::new("my token".to_owned());
2611    ///
2612    /// let guild_id = Id::new(1);
2613    /// let sticker_id = Id::new(2);
2614    ///
2615    /// client.delete_guild_sticker(guild_id, sticker_id).await?;
2616    /// # Ok(()) }
2617    /// ```
2618    pub const fn delete_guild_sticker(
2619        &self,
2620        guild_id: Id<GuildMarker>,
2621        sticker_id: Id<StickerMarker>,
2622    ) -> DeleteGuildSticker<'_> {
2623        DeleteGuildSticker::new(self, guild_id, sticker_id)
2624    }
2625
2626    /// Creates a test entitlement to a given SKU for a given guild or user. Discord
2627    /// will act as though that user or guild has entitlement to your premium offering.
2628    ///
2629    /// # Examples
2630    ///
2631    /// ```no_run
2632    /// use twilight_http::{Client, request::application::monetization::CreateTestEntitlementOwner};
2633    /// use twilight_model::id::Id;
2634    ///
2635    /// # #[tokio::main]
2636    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2637    /// let client = Client::new("my token".to_owned());
2638    ///
2639    /// let application_id = Id::new(1);
2640    /// let sku_id = Id::new(2);
2641    /// let owner = CreateTestEntitlementOwner::Guild(Id::new(3));
2642    ///
2643    /// client.create_test_entitlement(
2644    ///    application_id,
2645    ///    sku_id,
2646    ///    owner,
2647    /// ).await?;
2648    ///
2649    /// # Ok(()) }
2650    pub const fn create_test_entitlement(
2651        &self,
2652        application_id: Id<ApplicationMarker>,
2653        sku_id: Id<SkuMarker>,
2654        owner: CreateTestEntitlementOwner,
2655    ) -> CreateTestEntitlement<'_> {
2656        CreateTestEntitlement::new(self, application_id, sku_id, owner)
2657    }
2658
2659    /// Ends a poll in a channel.
2660    ///
2661    /// # Examples
2662    ///
2663    /// ```no_run
2664    /// use twilight_http::Client;
2665    /// use twilight_model::id::Id;
2666    ///
2667    /// # #[tokio::main]
2668    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2669    /// let client = Client::new("my token".to_owned());
2670    ///
2671    /// let channel_id = Id::new(1);
2672    /// let message_id = Id::new(2);
2673    ///
2674    /// client.end_poll(channel_id, message_id).await?;
2675    /// # Ok(()) }
2676    /// ```
2677    pub const fn end_poll(
2678        &self,
2679        channel_id: Id<ChannelMarker>,
2680        message_id: Id<MessageMarker>,
2681    ) -> EndPoll<'_> {
2682        EndPoll::new(self, channel_id, message_id)
2683    }
2684
2685    /// Deletes a currently-active test entitlement. Discord will act as though that user or
2686    /// guild no longer has entitlement to your premium offering.
2687    ///
2688    /// # Examples
2689    ///
2690    /// ```no_run
2691    /// use twilight_http::Client;
2692    /// use twilight_model::id::Id;
2693    ///
2694    /// # #[tokio::main]
2695    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2696    /// let client = Client::new("my token".to_owned());
2697    ///
2698    /// let application_id = Id::new(1);
2699    /// let entitlement_id = Id::new(2);
2700    ///
2701    /// client.delete_test_entitlement(
2702    ///   application_id,
2703    ///   entitlement_id,
2704    /// ).await?;
2705    ///
2706    /// # Ok(()) }
2707    pub const fn delete_test_entitlement(
2708        &self,
2709        application_id: Id<ApplicationMarker>,
2710        entitlement_id: Id<EntitlementMarker>,
2711    ) -> DeleteTestEntitlement<'_> {
2712        DeleteTestEntitlement::new(self, application_id, entitlement_id)
2713    }
2714
2715    /// /// Get the voters for an answer in a poll.
2716    ///
2717    /// # Examples
2718    ///
2719    /// ```no_run
2720    /// use twilight_http::Client;
2721    /// use twilight_model::id::Id;
2722    ///
2723    /// # #[tokio::main]
2724    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2725    /// let client = Client::new("my token".to_owned());
2726    ///
2727    /// let channel_id = Id::new(1);
2728    /// let message_id = Id::new(2);
2729    /// let answer_id = 1;
2730    ///
2731    /// let voters = client.get_answer_voters(channel_id, message_id, answer_id).await?;
2732    ///
2733    /// println!("{:?}", voters);
2734    /// # Ok(()) }
2735    pub const fn get_answer_voters(
2736        &self,
2737        channel_id: Id<ChannelMarker>,
2738        message_id: Id<MessageMarker>,
2739        answer_id: u8,
2740    ) -> GetAnswerVoters<'_> {
2741        GetAnswerVoters::new(self, channel_id, message_id, answer_id)
2742    }
2743
2744    /// Returns all SKUs for a given application.
2745    ///
2746    /// # Examples
2747    ///
2748    /// ```no_run
2749    /// use twilight_http::Client;
2750    /// use twilight_model::id::Id;
2751    ///
2752    /// # #[tokio::main]
2753    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2754    /// let client = Client::new("my token".to_owned());
2755    ///
2756    /// let application_id = Id::new(1);
2757    ///
2758    /// let skus = client.get_skus(application_id).await?;
2759    ///
2760    /// # Ok(()) }
2761    pub const fn get_skus(&self, application_id: Id<ApplicationMarker>) -> GetSKUs<'_> {
2762        GetSKUs::new(self, application_id)
2763    }
2764
2765    /// Gets all emojis associated with an application
2766    ///
2767    /// # Examples
2768    ///
2769    /// ```no_run
2770    /// use twilight_http::Client;
2771    /// use twilight_model::id::Id;
2772    ///
2773    /// # #[tokio::main]
2774    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2775    /// let client = Client::new("my token".to_owned());
2776    ///
2777    /// let application_id = Id::new(1);
2778    ///
2779    /// let emojis = client.get_application_emojis(application_id).await?;
2780    ///
2781    /// # Ok(()) }
2782    /// ```
2783    pub const fn get_application_emojis(
2784        &self,
2785        application_id: Id<ApplicationMarker>,
2786    ) -> ListApplicationEmojis<'_> {
2787        ListApplicationEmojis::new(self, application_id)
2788    }
2789
2790    /// Adds an emoji to an application
2791    ///
2792    /// Needs to be base64 encoded and prefixed and tagged.
2793    /// Can be up to 128x128 in size
2794    ///
2795    /// # Examples
2796    ///
2797    /// ```no_run
2798    /// use twilight_http::Client;
2799    /// use twilight_model::id::Id;
2800    ///
2801    /// # #[tokio::main]
2802    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2803    /// let client = Client::new("my token".to_owned());
2804    ///
2805    /// let application_id = Id::new(1);
2806    ///
2807    /// client
2808    ///     .add_application_emoji(application_id, "name", "data:image/png;base64,image_data")
2809    ///     .await?;
2810    ///
2811    /// # Ok(()) }
2812    /// ```
2813    pub const fn add_application_emoji<'a>(
2814        &'a self,
2815        application_id: Id<ApplicationMarker>,
2816        name: &'a str,
2817        image: &'a str,
2818    ) -> AddApplicationEmoji<'a> {
2819        AddApplicationEmoji::new(self, application_id, name, image)
2820    }
2821
2822    /// Updates an emoji associated with an application.
2823    ///
2824    /// # Examples
2825    ///
2826    /// ```no_run
2827    /// use twilight_http::Client;
2828    /// use twilight_model::id::Id;
2829    ///
2830    /// # #[tokio::main]
2831    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2832    /// let client = Client::new("my token".to_owned());
2833    ///
2834    /// let application_id = Id::new(1);
2835    /// let emoji_id = Id::new(2);
2836    ///
2837    /// client
2838    ///     .update_application_emoji(application_id, emoji_id, "new emoji name")
2839    ///     .await?;
2840    ///
2841    /// # Ok(()) }
2842    /// ```
2843    pub const fn update_application_emoji<'a>(
2844        &'a self,
2845        application_id: Id<ApplicationMarker>,
2846        emoji_id: Id<EmojiMarker>,
2847        name: &'a str,
2848    ) -> UpdateApplicationEmoji<'a> {
2849        UpdateApplicationEmoji::new(self, application_id, emoji_id, name)
2850    }
2851
2852    /// Deletes an emoji associated with an application.
2853    ///
2854    /// # Examples
2855    ///
2856    /// ```no_run
2857    /// use twilight_http::Client;
2858    /// use twilight_model::id::Id;
2859    ///
2860    /// # #[tokio::main]
2861    /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
2862    /// let client = Client::new("my token".to_owned());
2863    ///
2864    /// let application_id = Id::new(1);
2865    /// let emoji_id = Id::new(2);
2866    ///
2867    /// client
2868    ///     .delete_application_emoji(application_id, emoji_id)
2869    ///     .await?;
2870    ///
2871    /// # Ok(()) }
2872    /// ```
2873    pub const fn delete_application_emoji(
2874        &self,
2875        application_id: Id<ApplicationMarker>,
2876        emoji_id: Id<EmojiMarker>,
2877    ) -> DeleteApplicationEmoji<'_> {
2878        DeleteApplicationEmoji::new(self, application_id, emoji_id)
2879    }
2880
2881    /// Execute a request, returning a future resolving to a [`Response`].
2882    ///
2883    /// # Errors
2884    ///
2885    /// Returns an [`ErrorType::Unauthorized`] error type if the configured
2886    /// token has become invalid due to expiration, revocation, etc.
2887    ///
2888    /// [`Response`]: super::response::Response
2889    pub fn request<T>(&self, request: Request) -> ResponseFuture<T> {
2890        match self.try_request::<T>(request) {
2891            Ok(future) => future,
2892            Err(source) => ResponseFuture::error(source),
2893        }
2894    }
2895
2896    fn try_request<T>(&self, request: Request) -> Result<ResponseFuture<T>, Error> {
2897        if let Some(token_invalidated) = self.token_invalidated.as_ref()
2898            && token_invalidated.load(Ordering::Relaxed)
2899        {
2900            return Err(Error {
2901                kind: ErrorType::Unauthorized,
2902                source: None,
2903            });
2904        }
2905
2906        let Request {
2907            body,
2908            form,
2909            headers: req_headers,
2910            method,
2911            mut path,
2912            use_authorization_token,
2913        } = request;
2914
2915        let protocol = if self.use_http { "http" } else { "https" };
2916        let host = self.proxy.as_deref().unwrap_or("discord.com");
2917
2918        let url = format!("{protocol}://{host}/api/v{API_VERSION}/{path}");
2919
2920        let mut builder = hyper::Request::builder().method(method.name()).uri(&url);
2921
2922        if use_authorization_token && let Some(token) = self.token.as_deref() {
2923            let value = HeaderValue::from_str(token).map_err(|source| {
2924                let name = AUTHORIZATION.to_string();
2925
2926                Error {
2927                    kind: ErrorType::CreatingHeader { name },
2928                    source: Some(Box::new(source)),
2929                }
2930            })?;
2931
2932            if let Some(headers) = builder.headers_mut() {
2933                headers.insert(AUTHORIZATION, value);
2934            }
2935        }
2936
2937        if let Some(headers) = builder.headers_mut() {
2938            if let Some(form) = &form {
2939                headers.insert(CONTENT_LENGTH, HeaderValue::from(form.len()));
2940                if let Ok(content_type) = HeaderValue::try_from(form.content_type()) {
2941                    headers.insert(CONTENT_TYPE, content_type);
2942                }
2943            } else if let Some(bytes) = &body {
2944                headers.insert(CONTENT_LENGTH, HeaderValue::from(bytes.len()));
2945                headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
2946            } else if matches!(method, Method::Put | Method::Post | Method::Patch) {
2947                headers.insert(CONTENT_LENGTH, HeaderValue::from(0));
2948            }
2949
2950            #[cfg(feature = "decompression")]
2951            headers.insert(
2952                hyper::header::ACCEPT_ENCODING,
2953                HeaderValue::from_static("br"),
2954            );
2955
2956            headers.insert(USER_AGENT, HeaderValue::from_static(TWILIGHT_USER_AGENT));
2957
2958            if let Some(req_headers) = req_headers {
2959                for (maybe_name, value) in req_headers {
2960                    if let Some(name) = maybe_name {
2961                        headers.insert(name, value);
2962                    }
2963                }
2964            }
2965
2966            if let Some(default_headers) = &self.default_headers {
2967                for (name, value) in default_headers {
2968                    headers.insert(name, value.clone());
2969                }
2970            }
2971        }
2972
2973        let try_req = if let Some(form) = form {
2974            builder.body(Full::from(form.build()))
2975        } else if let Some(bytes) = body {
2976            builder.body(Full::from(bytes))
2977        } else {
2978            builder.body(Full::default())
2979        };
2980
2981        let http_request = try_req.map_err(|source| Error {
2982            kind: ErrorType::BuildingRequest,
2983            source: Some(Box::new(source)),
2984        })?;
2985
2986        // For requests that don't use an authorization token we don't need to
2987        // remember whether the token is invalid. This may be for requests such
2988        // as webhooks and interactions.
2989        let invalid_token = use_authorization_token
2990            .then(|| self.token_invalidated.clone())
2991            .flatten();
2992
2993        if let Some(i) = path.find('?') {
2994            path.truncate(i);
2995        }
2996        let response = ResponseFuture::new(
2997            self.http.clone(),
2998            invalid_token,
2999            http_request,
3000            tracing::info_span!("req", method = method.name(), url = url),
3001            self.timeout,
3002            self.ratelimiter.clone(),
3003            Endpoint { method, path },
3004        );
3005
3006        Ok(response)
3007    }
3008}
3009
3010#[cfg(test)]
3011mod tests {
3012    use super::Client;
3013
3014    #[test]
3015    fn client_debug_with_token() {
3016        assert!(
3017            format!("{:?}", Client::new("Bot foo".to_owned())).contains("token: Some(<redacted>)")
3018        );
3019        assert!(format!("{:?}", Client::builder().build()).contains("token: None"));
3020    }
3021}