Compare commits
4 Commits
995f5c2b86
...
714948fa14
Author | SHA1 | Date |
---|---|---|
kozabrada123 | 714948fa14 | |
kozabrada123 | 0a1c51dddd | |
kozabrada123 | 5d0a65a9a9 | |
kozabrada123 | 62d48d61fe |
|
@ -11,7 +11,10 @@ use crate::{
|
|||
errors::{ChorusError, ChorusResult},
|
||||
instance::{ChorusUser, Instance},
|
||||
ratelimiter::ChorusRequest,
|
||||
types::{LimitType, PublicUser, Snowflake, User, UserModifySchema, UserProfile, UserSettings},
|
||||
types::{
|
||||
DeleteDisableUserSchema, LimitType, PublicUser, Snowflake, User, UserModifyProfileSchema,
|
||||
UserModifySchema, UserProfile, UserProfileMetadata, UserSettings, VerifyUserEmailChangeResponse, VerifyUserEmailChangeSchema,
|
||||
},
|
||||
};
|
||||
|
||||
impl ChorusUser {
|
||||
|
@ -96,23 +99,54 @@ impl ChorusUser {
|
|||
chorus_request.deserialize_response::<User>(self).await
|
||||
}
|
||||
|
||||
/// Deletes the user from the Instance.
|
||||
/// Disables the current user's account.
|
||||
///
|
||||
/// Invalidates all active tokens.
|
||||
///
|
||||
/// Requires the user's current password (if any)
|
||||
///
|
||||
/// # Notes
|
||||
/// Requires MFA
|
||||
///
|
||||
/// # Reference
|
||||
/// See <https://discord-userdoccers.vercel.app/resources/user#disable-user>
|
||||
pub async fn delete(mut self) -> ChorusResult<()> {
|
||||
/// See <https://docs.discord.sex/resources/user#disable-user>
|
||||
pub async fn disable(&mut self, schema: DeleteDisableUserSchema) -> ChorusResult<()> {
|
||||
let request = Client::new()
|
||||
.post(format!(
|
||||
"{}/users/@me/disable",
|
||||
self.belongs_to.read().unwrap().urls.api
|
||||
))
|
||||
.header("Authorization", self.token())
|
||||
.json(&schema);
|
||||
let chorus_request = ChorusRequest {
|
||||
request,
|
||||
limit_type: LimitType::default(),
|
||||
};
|
||||
chorus_request.handle_request_as_result(self).await
|
||||
}
|
||||
|
||||
/// Deletes the current user from the Instance.
|
||||
///
|
||||
/// Requires the user's current password (if any)
|
||||
///
|
||||
/// # Notes
|
||||
/// Requires MFA
|
||||
///
|
||||
/// # Reference
|
||||
/// See <https://docs.discord.sex/resources/user#delete-user>
|
||||
pub async fn delete(&mut self, schema: DeleteDisableUserSchema) -> ChorusResult<()> {
|
||||
let request = Client::new()
|
||||
.post(format!(
|
||||
"{}/users/@me/delete",
|
||||
self.belongs_to.read().unwrap().urls.api
|
||||
))
|
||||
.header("Authorization", self.token())
|
||||
.header("Content-Type", "application/json");
|
||||
.json(&schema);
|
||||
let chorus_request = ChorusRequest {
|
||||
request,
|
||||
limit_type: LimitType::default(),
|
||||
};
|
||||
chorus_request.handle_request_as_result(&mut self).await
|
||||
chorus_request.handle_request_as_result(self).await
|
||||
}
|
||||
|
||||
/// Gets a user's profile object by their id.
|
||||
|
@ -133,6 +167,68 @@ impl ChorusUser {
|
|||
pub async fn get_user_profile(&mut self, id: Snowflake) -> ChorusResult<UserProfile> {
|
||||
User::get_profile(self, id).await
|
||||
}
|
||||
|
||||
/// Modifies the current user's profile.
|
||||
///
|
||||
/// Returns the updated [UserProfileMetadata].
|
||||
///
|
||||
/// # Notes
|
||||
/// This function is a wrapper around [`User::modify_profile`].
|
||||
///
|
||||
/// # Reference
|
||||
/// See <https://docs.discord.sex/resources/user#modify-user-profile>
|
||||
pub async fn modify_profile(
|
||||
&mut self,
|
||||
schema: UserModifyProfileSchema,
|
||||
) -> ChorusResult<UserProfileMetadata> {
|
||||
User::modify_profile(self, schema).await
|
||||
}
|
||||
|
||||
/// Initiates the email change process.
|
||||
///
|
||||
/// Sends a verification code to the current user's email.
|
||||
///
|
||||
/// Should be followed up with [Self::verify_email_change]
|
||||
///
|
||||
/// # Reference
|
||||
/// See <https://docs.discord.sex/resources/user#modify-user-email>
|
||||
pub async fn initiate_email_change(&mut self) -> ChorusResult<()> {
|
||||
let request = Client::new()
|
||||
.put(format!(
|
||||
"{}/users/@me/email",
|
||||
self.belongs_to.read().unwrap().urls.api
|
||||
))
|
||||
.header("Authorization", self.token());
|
||||
let chorus_request = ChorusRequest {
|
||||
request,
|
||||
limit_type: LimitType::default(),
|
||||
};
|
||||
chorus_request.handle_request_as_result(self).await
|
||||
}
|
||||
|
||||
/// Verifies a code sent to change the current user's email.
|
||||
///
|
||||
/// Should be the follow-up to [Self::initiate_email_change]
|
||||
///
|
||||
/// This endpoint returns a token which can be used with [Self::modify]
|
||||
/// to set a new email address (email_token).
|
||||
///
|
||||
/// # Reference
|
||||
/// See <https://docs.discord.sex/resources/user#modify-user-email>
|
||||
pub async fn verify_email_change(&mut self, schema: VerifyUserEmailChangeSchema) -> ChorusResult<VerifyUserEmailChangeResponse> {
|
||||
let request = Client::new()
|
||||
.post(format!(
|
||||
"{}/users/@me/email/verify-code",
|
||||
self.belongs_to.read().unwrap().urls.api
|
||||
))
|
||||
.header("Authorization", self.token())
|
||||
.json(&schema);
|
||||
let chorus_request = ChorusRequest {
|
||||
request,
|
||||
limit_type: LimitType::default(),
|
||||
};
|
||||
chorus_request.deserialize_response::<VerifyUserEmailChangeResponse>(self).await
|
||||
}
|
||||
}
|
||||
|
||||
impl User {
|
||||
|
@ -247,4 +343,28 @@ impl User {
|
|||
.deserialize_response::<UserProfile>(user)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Modifies the current user's profile.
|
||||
///
|
||||
/// Returns the updated [UserProfileMetadata].
|
||||
///
|
||||
/// # Reference
|
||||
/// See <https://docs.discord.sex/resources/user#modify-user-profile>
|
||||
pub async fn modify_profile(
|
||||
user: &mut ChorusUser,
|
||||
schema: UserModifyProfileSchema,
|
||||
) -> ChorusResult<UserProfileMetadata> {
|
||||
let url_api = user.belongs_to.read().unwrap().urls.api.clone();
|
||||
let request: reqwest::RequestBuilder = Client::new()
|
||||
.patch(format!("{}/users/@me/profile", url_api))
|
||||
.header("Authorization", user.token())
|
||||
.json(&schema);
|
||||
let chorus_request = ChorusRequest {
|
||||
request,
|
||||
limit_type: LimitType::Global,
|
||||
};
|
||||
chorus_request
|
||||
.deserialize_response::<UserProfileMetadata>(user)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::collections::HashMap;
|
|||
use chrono::NaiveDate;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::Snowflake;
|
||||
use crate::types::{Snowflake, ThemeColors};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
|
@ -31,7 +31,7 @@ pub struct UserModifySchema {
|
|||
// TODO: Add a CDN data type
|
||||
pub avatar: Option<String>,
|
||||
/// Note: This is not yet implemented on Spacebar
|
||||
pub avatar_decoration_id: Option<Snowflake>,
|
||||
pub avatar_decoration_id: Option<Snowflake>,
|
||||
/// Note: This is not yet implemented on Spacebar
|
||||
pub avatar_decoration_sku_id: Option<Snowflake>,
|
||||
/// The user's email address; if changing from a verified email, email_token must be provided
|
||||
|
@ -41,7 +41,12 @@ pub struct UserModifySchema {
|
|||
pub email: Option<String>,
|
||||
/// The user's email token from their previous email, required if a new email is set.
|
||||
///
|
||||
/// See <https://docs.discord.sex/resources/user#modify-user-email> and <https://docs.discord.sex/resources/user#verify-user-email-change>
|
||||
/// See:
|
||||
///
|
||||
/// - the endpoints <https://docs.discord.sex/resources/user#modify-user-email> and <https://docs.discord.sex/resources/user#verify-user-email-change>
|
||||
///
|
||||
/// - the relevant methods [`ChorusUser::initiate_email_change`](crate::instance::ChorusUser::initiate_email_change) and [`ChorusUser::verify_email_change`](crate::instance::ChorusUser::verify_email_change)
|
||||
///
|
||||
/// for changing the user's email.
|
||||
///
|
||||
/// # Note
|
||||
|
@ -106,3 +111,73 @@ pub struct PrivateChannelCreateSchema {
|
|||
pub access_tokens: Option<Vec<String>>,
|
||||
pub nicks: Option<HashMap<Snowflake, String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||
/// A schema used to modify the current user's profile.
|
||||
///
|
||||
/// Similar to [crate::types::UserProfileMetadata]
|
||||
///
|
||||
/// See <https://docs.discord.sex/resources/user#modify-user-profile>
|
||||
pub struct UserModifyProfileSchema {
|
||||
// Note: one of these causes a 500 if it is sent
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// The user's new pronouns (max 40 characters)
|
||||
pub pronouns: Option<String>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// The user's new bio (max 190 characters)
|
||||
pub bio: Option<String>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
// TODO: Add banner -- do we have an image data struct
|
||||
/// The user's new accent color encoded as an i32 representation of a hex color code
|
||||
pub accent_color: Option<i32>,
|
||||
|
||||
// Note: without the skip serializing this currently (2024/07/28) causes a 500!
|
||||
//
|
||||
// Which in turns locks the user's account, requiring phone number verification
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// The user's new [ThemeColors]
|
||||
pub theme_colors: Option<ThemeColors>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// The user's new profile popup animation particle type
|
||||
pub popout_animation_particle_type: Option<Snowflake>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// The user's new profile emoji id
|
||||
pub emoji_id: Option<Snowflake>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
/// The user's new profile ffect id
|
||||
pub profile_effect_id: Option<Snowflake>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||
/// A schema used to delete or disable the current user's profile.
|
||||
///
|
||||
/// See <https://docs.discord.sex/resources/user#disable-user> and
|
||||
/// <https://docs.discord.sex/resources/user#delete-user>
|
||||
pub struct DeleteDisableUserSchema {
|
||||
/// The user's current password, if any
|
||||
pub password: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||
/// A schema used for [ChorusUser::verify_email_change](crate::instance::ChorusUser::verify_email_change)
|
||||
///
|
||||
/// See <https://docs.discord.sex/resources/user#verify-user-email-change>
|
||||
pub struct VerifyUserEmailChangeSchema {
|
||||
/// The verification code sent to the user's email
|
||||
pub code: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||
/// The return type of [ChorusUser::verify_email_change](crate::instance::ChorusUser::verify_email_change)
|
||||
///
|
||||
/// See <https://docs.discord.sex/resources/user#verify-user-email-change>
|
||||
pub struct VerifyUserEmailChangeResponse {
|
||||
/// The email_token to be used in [ChorusUser::modify](crate::instance::ChorusUser::modify)
|
||||
#[serde(rename = "token")]
|
||||
pub email_token: String,
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use chorus::gateway::{Gateway, GatewayOptions};
|
||||
use chorus::types::{IntoShared, PermissionFlags};
|
||||
use chorus::types::{DeleteDisableUserSchema, IntoShared, PermissionFlags};
|
||||
use chorus::{
|
||||
instance::{ChorusUser, Instance},
|
||||
types::{
|
||||
Channel, ChannelCreateSchema, Guild, GuildCreateSchema, RegisterSchema,
|
||||
RoleCreateModifySchema, RoleObject, Shared
|
||||
RoleCreateModifySchema, RoleObject, Shared,
|
||||
},
|
||||
UrlBundle,
|
||||
};
|
||||
|
@ -59,9 +59,12 @@ impl TestBundle {
|
|||
|
||||
// Set up a test by creating an Instance and a User. Reduces Test boilerplate.
|
||||
pub(crate) async fn setup() -> TestBundle {
|
||||
|
||||
// So we can get logs when tests fail
|
||||
let _ = simple_logger::SimpleLogger::with_level(simple_logger::SimpleLogger::new(), log::LevelFilter::Debug).init();
|
||||
let _ = simple_logger::SimpleLogger::with_level(
|
||||
simple_logger::SimpleLogger::new(),
|
||||
log::LevelFilter::Debug,
|
||||
)
|
||||
.init();
|
||||
|
||||
let instance = Instance::new("http://localhost:3001/api").await.unwrap();
|
||||
// Requires the existence of the below user.
|
||||
|
@ -141,5 +144,9 @@ pub(crate) async fn setup() -> TestBundle {
|
|||
pub(crate) async fn teardown(mut bundle: TestBundle) {
|
||||
let id = bundle.guild.read().unwrap().id;
|
||||
Guild::delete(&mut bundle.user, id).await.unwrap();
|
||||
bundle.user.delete().await.unwrap()
|
||||
bundle
|
||||
.user
|
||||
.delete(DeleteDisableUserSchema { password: None })
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue