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