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