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