Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions twilight-http-ratelimiting/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ pub enum Path {
ApplicationGuildCommand(u64),
/// Operating on a specific command in a guild.
ApplicationGuildCommandId(u64),
/// Operating on current user application,
ApplicationsMe,
/// Operating on a channel.
ChannelsId(u64),
/// Operating on a channel's followers.
Expand Down Expand Up @@ -330,6 +332,7 @@ impl FromStr for Path {
let parts = s.split('/').skip(skip).collect::<Vec<&str>>();

Ok(match parts[..] {
["applications", "me"] => ApplicationsMe,
["applications", id, "commands"] => ApplicationCommand(parse_id(id)?),
["applications", id, "commands", _] => ApplicationCommandId(parse_id(id)?),
["applications", id, "guilds", _, "commands"]
Expand Down
7 changes: 6 additions & 1 deletion twilight-http/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::request::{
update_guild_onboarding::{UpdateGuildOnboarding, UpdateGuildOnboardingFields},
GetGuildOnboarding,
},
GetCurrentAuthorizationInformation,
GetCurrentAuthorizationInformation, UpdateCurrentUserApplication,
};
#[allow(deprecated)]
use crate::{
Expand Down Expand Up @@ -698,6 +698,11 @@ impl Client {
GetUserApplicationInfo::new(self)
}

/// Update the current user's application.
pub const fn update_current_user_application(&self) -> UpdateCurrentUserApplication<'_> {
UpdateCurrentUserApplication::new(self)
}

/// Update the current user.
///
/// All parameters are optional. If the username is changed, it may cause the discriminator to
Expand Down
2 changes: 2 additions & 0 deletions twilight-http/src/request/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ mod get_user_application;
mod get_voice_regions;
mod multipart;
mod try_into_request;
mod update_user_application;

pub use self::{
audit_reason::AuditLogReason,
Expand All @@ -69,6 +70,7 @@ pub use self::{
get_voice_regions::GetVoiceRegions,
multipart::Form,
try_into_request::TryIntoRequest,
update_user_application::UpdateCurrentUserApplication,
};
pub use twilight_http_ratelimiting::request::Method;

Expand Down
2 changes: 2 additions & 0 deletions twilight-http/src/request/try_into_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ mod private {
CreateGuildFromTemplate, CreateTemplate, DeleteTemplate, GetTemplate, GetTemplates,
SyncTemplate, UpdateTemplate,
},
update_user_application::UpdateCurrentUserApplication,
user::{
CreatePrivateChannel, GetCurrentUser, GetCurrentUserConnections,
GetCurrentUserGuildMember, GetCurrentUserGuilds, GetUser, LeaveGuild,
Expand Down Expand Up @@ -269,6 +270,7 @@ mod private {
impl Sealed for UpdateWebhook<'_> {}
impl Sealed for UpdateWebhookMessage<'_> {}
impl Sealed for UpdateWebhookWithToken<'_> {}
impl Sealed for UpdateCurrentUserApplication<'_> {}
}

use super::base::Request;
Expand Down
180 changes: 180 additions & 0 deletions twilight-http/src/request/update_user_application.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
use std::future::IntoFuture;

use serde::Serialize;
use twilight_model::oauth::{Application, ApplicationFlags, InstallParams};

use crate::{
client::Client,
error::Error,
request::{Nullable, Request, TryIntoRequest},
response::{Response, ResponseFuture},
routing::Route,
};

#[derive(Serialize)]
struct UpdateCurrentUserApplicationFields<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
cover_image: Option<Nullable<&'a str>>,
#[serde(skip_serializing_if = "Option::is_none")]
custom_install_url: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
flags: Option<ApplicationFlags>,
#[serde(skip_serializing_if = "Option::is_none")]
icon: Option<Nullable<&'a str>>,
#[serde(skip_serializing_if = "Option::is_none")]
install_params: Option<InstallParams>,
#[serde(skip_serializing_if = "Option::is_none")]
interactions_endpoint_url: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
role_connections_verification_url: Option<&'a str>,
#[serde(skip_serializing_if = "Option::is_none")]
tags: Option<Vec<&'a str>>,
}

/// Update the current user's application.
///
/// Returns the newly updated application.
///
/// Refer to [Discord Docs/Update Current User Application][1].
///
/// # Examples
///
/// ```no_run
/// # #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use std::env;
/// use twilight_http::Client;
///
/// let bearer_token = env::var("BEARER_TOKEN")?;
///
/// let client = Client::new(bearer_token);
/// let response = client
/// .update_current_user_application()
/// .description("My cool application")
/// .await?;
/// let application = response.model().await?;
///
/// println!("Application: {}", application.description);
///
/// # Ok(()) }
/// ```
///
/// [1]: https://discord.com/developers/docs/resources/application#edit-current-application
#[must_use = "requests must be configured and executed"]
pub struct UpdateCurrentUserApplication<'a> {
fields: UpdateCurrentUserApplicationFields<'a>,
http: &'a Client,
}

impl<'a> UpdateCurrentUserApplication<'a> {
pub(crate) const fn new(http: &'a Client) -> Self {
Self {
fields: UpdateCurrentUserApplicationFields {
cover_image: None,
custom_install_url: None,
description: None,
flags: None,
icon: None,
install_params: None,
interactions_endpoint_url: None,
role_connections_verification_url: None,
tags: None,
},
http,
}
}

/// Sets the cover image of the application.
pub const fn cover_image(mut self, cover_image: Option<&'a str>) -> Self {
self.fields.cover_image = Some(Nullable(cover_image));

self
}

/// Sets the custom install URL of the application.
pub const fn custom_install_url(mut self, custom_install_url: &'a str) -> Self {
self.fields.custom_install_url = Some(custom_install_url);

self
}

/// Sets the description of the application.
pub const fn description(mut self, description: &'a str) -> Self {
self.fields.description = Some(description);

self
}

/// Sets the flags of the application.
/// Only limited intent flags (`GATEWAY_PRESENCE_LIMITED`, `GATEWAY_GUILD_MEMBERS_LIMITED`,
/// and `GATEWAY_MESSAGE_CONTENT_LIMITED`) can be updated via the API.
pub const fn flags(mut self, flags: ApplicationFlags) -> Self {
self.fields.flags = Some(flags);

self
}

/// Sets the icon of the application.
pub const fn icon(mut self, icon: Option<&'a str>) -> Self {
self.fields.icon = Some(Nullable(icon));

self
}

/// Sets the install params of the application.
pub fn install_params(mut self, install_params: InstallParams) -> Self {
self.fields.install_params = Some(install_params);

self
}

/// Sets the interactions endpoint URL of the application.
pub const fn interactions_endpoint_url(mut self, interactions_endpoint_url: &'a str) -> Self {
self.fields.interactions_endpoint_url = Some(interactions_endpoint_url);

self
}

/// Sets the role connections verification URL of the application.
pub const fn role_connections_verification_url(
mut self,
role_connections_verification_url: &'a str,
) -> Self {
self.fields.role_connections_verification_url = Some(role_connections_verification_url);

self
}

/// Sets the tags of the application.
pub fn tags(mut self, tags: Vec<&'a str>) -> Self {
self.fields.tags = Some(tags);

self
}
}

impl IntoFuture for UpdateCurrentUserApplication<'_> {
type Output = Result<Response<Application>, Error>;

type IntoFuture = ResponseFuture<Application>;

fn into_future(self) -> Self::IntoFuture {
let http = self.http;

match self.try_into_request() {
Ok(request) => http.request(request),
Err(source) => ResponseFuture::error(source),
}
}
}

impl TryIntoRequest for UpdateCurrentUserApplication<'_> {
fn try_into_request(self) -> Result<Request, Error> {
let mut request = Request::builder(&Route::UpdateCurrentUserApplication);

request = request.json(&self.fields)?;

Ok(request.build())
}
}
23 changes: 19 additions & 4 deletions twilight-http/src/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ use twilight_model::id::{marker::RoleMarker, Id};
#[non_exhaustive]
pub enum Route<'a> {
/// Route information to add a user to a guild.
AddGuildMember { guild_id: u64, user_id: u64 },
AddGuildMember {
guild_id: u64,
user_id: u64,
},
/// Route information to add a role to guild member.
AddMemberRole {
/// The ID of the guild.
Expand Down Expand Up @@ -1099,6 +1102,7 @@ pub enum Route<'a> {
token: &'a str,
webhook_id: u64,
},
UpdateCurrentUserApplication,
}

impl<'a> Route<'a> {
Expand Down Expand Up @@ -1249,6 +1253,7 @@ impl<'a> Route<'a> {
| Self::UpdateTemplate { .. }
| Self::UpdateUserVoiceState { .. }
| Self::UpdateWebhookMessage { .. }
| Self::UpdateCurrentUserApplication
| Self::UpdateWebhook { .. } => Method::Patch,
Self::CreateChannel { .. }
| Self::CreateGlobalCommand { .. }
Expand Down Expand Up @@ -1537,7 +1542,9 @@ impl<'a> Route<'a> {
Path::ApplicationGuildCommandId(application_id)
}
Self::GetCurrentAuthorizationInformation => Path::OauthMe,
Self::GetCurrentUserApplicationInfo => Path::OauthApplicationsMe,
Self::GetCurrentUserApplicationInfo | Self::UpdateCurrentUserApplication => {
Path::ApplicationsMe
}
Self::GetCurrentUser | Self::GetUser { .. } | Self::UpdateCurrentUser => Path::UsersId,
Self::GetCurrentUserGuildMember { .. } => Path::UsersIdGuildsIdMember,
Self::GetEmoji { guild_id, .. } | Self::UpdateEmoji { guild_id, .. } => {
Expand Down Expand Up @@ -2341,7 +2348,9 @@ impl Display for Route<'_> {
f.write_str("/permissions")
}
Route::GetCurrentAuthorizationInformation => f.write_str("oauth2/@me"),
Route::GetCurrentUserApplicationInfo => f.write_str("oauth2/applications/@me"),
Route::GetCurrentUserApplicationInfo | Route::UpdateCurrentUserApplication => {
f.write_str("applications/@me")
}
Route::GetCurrentUser | Route::UpdateCurrentUser => f.write_str("users/@me"),
Route::GetCurrentUserGuildMember { guild_id } => {
f.write_str("users/@me/guilds/")?;
Expand Down Expand Up @@ -4005,7 +4014,13 @@ mod tests {
#[test]
fn get_current_user_application_info() {
let route = Route::GetCurrentUserApplicationInfo;
assert_eq!(route.to_string(), "oauth2/applications/@me");
assert_eq!(route.to_string(), "applications/@me");
}

#[test]
fn update_current_user_application() {
let route = Route::UpdateCurrentUserApplication;
assert_eq!(route.to_string(), "applications/@me");
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion twilight-model/src/guild/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ use serde::{
};
use std::fmt::{Formatter, Result as FmtResult};

#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Hash)]
pub struct Guild {
pub afk_channel_id: Option<Id<ChannelMarker>>,
pub afk_timeout: AfkTimeout,
Expand Down
Loading