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