Compare commits
1 Commits
714948fa14
...
995f5c2b86
Author | SHA1 | Date |
---|---|---|
kozabrada123 | 995f5c2b86 |
|
@ -11,10 +11,7 @@ use crate::{
|
||||||
errors::{ChorusError, ChorusResult},
|
errors::{ChorusError, ChorusResult},
|
||||||
instance::{ChorusUser, Instance},
|
instance::{ChorusUser, Instance},
|
||||||
ratelimiter::ChorusRequest,
|
ratelimiter::ChorusRequest,
|
||||||
types::{
|
types::{LimitType, PublicUser, Snowflake, User, UserModifySchema, UserProfile, UserSettings},
|
||||||
DeleteDisableUserSchema, LimitType, PublicUser, Snowflake, User, UserModifyProfileSchema,
|
|
||||||
UserModifySchema, UserProfile, UserProfileMetadata, UserSettings, VerifyUserEmailChangeResponse, VerifyUserEmailChangeSchema,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl ChorusUser {
|
impl ChorusUser {
|
||||||
|
@ -99,54 +96,23 @@ impl ChorusUser {
|
||||||
chorus_request.deserialize_response::<User>(self).await
|
chorus_request.deserialize_response::<User>(self).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Disables the current user's account.
|
/// Deletes the user from the Instance.
|
||||||
///
|
|
||||||
/// Invalidates all active tokens.
|
|
||||||
///
|
|
||||||
/// Requires the user's current password (if any)
|
|
||||||
///
|
|
||||||
/// # Notes
|
|
||||||
/// Requires MFA
|
|
||||||
///
|
///
|
||||||
/// # Reference
|
/// # Reference
|
||||||
/// See <https://docs.discord.sex/resources/user#disable-user>
|
/// See <https://discord-userdoccers.vercel.app/resources/user#disable-user>
|
||||||
pub async fn disable(&mut self, schema: DeleteDisableUserSchema) -> ChorusResult<()> {
|
pub async fn delete(mut self) -> 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()
|
let request = Client::new()
|
||||||
.post(format!(
|
.post(format!(
|
||||||
"{}/users/@me/delete",
|
"{}/users/@me/delete",
|
||||||
self.belongs_to.read().unwrap().urls.api
|
self.belongs_to.read().unwrap().urls.api
|
||||||
))
|
))
|
||||||
.header("Authorization", self.token())
|
.header("Authorization", self.token())
|
||||||
.json(&schema);
|
.header("Content-Type", "application/json");
|
||||||
let chorus_request = ChorusRequest {
|
let chorus_request = ChorusRequest {
|
||||||
request,
|
request,
|
||||||
limit_type: LimitType::default(),
|
limit_type: LimitType::default(),
|
||||||
};
|
};
|
||||||
chorus_request.handle_request_as_result(self).await
|
chorus_request.handle_request_as_result(&mut self).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a user's profile object by their id.
|
/// Gets a user's profile object by their id.
|
||||||
|
@ -167,68 +133,6 @@ impl ChorusUser {
|
||||||
pub async fn get_user_profile(&mut self, id: Snowflake) -> ChorusResult<UserProfile> {
|
pub async fn get_user_profile(&mut self, id: Snowflake) -> ChorusResult<UserProfile> {
|
||||||
User::get_profile(self, id).await
|
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 {
|
impl User {
|
||||||
|
@ -343,28 +247,4 @@ impl User {
|
||||||
.deserialize_response::<UserProfile>(user)
|
.deserialize_response::<UserProfile>(user)
|
||||||
.await
|
.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 chrono::NaiveDate;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::{Snowflake, ThemeColors};
|
use crate::types::Snowflake;
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
|
@ -41,12 +41,7 @@ pub struct UserModifySchema {
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
/// The user's email token from their previous email, required if a new email is set.
|
/// The user's email token from their previous email, required if a new email is set.
|
||||||
///
|
///
|
||||||
/// See:
|
/// See <https://docs.discord.sex/resources/user#modify-user-email> and <https://docs.discord.sex/resources/user#verify-user-email-change>
|
||||||
///
|
|
||||||
/// - 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.
|
/// for changing the user's email.
|
||||||
///
|
///
|
||||||
/// # Note
|
/// # Note
|
||||||
|
@ -111,73 +106,3 @@ pub struct PrivateChannelCreateSchema {
|
||||||
pub access_tokens: Option<Vec<String>>,
|
pub access_tokens: Option<Vec<String>>,
|
||||||
pub nicks: Option<HashMap<Snowflake, 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 std::str::FromStr;
|
||||||
|
|
||||||
use chorus::gateway::{Gateway, GatewayOptions};
|
use chorus::gateway::{Gateway, GatewayOptions};
|
||||||
use chorus::types::{DeleteDisableUserSchema, IntoShared, PermissionFlags};
|
use chorus::types::{IntoShared, PermissionFlags};
|
||||||
use chorus::{
|
use chorus::{
|
||||||
instance::{ChorusUser, Instance},
|
instance::{ChorusUser, Instance},
|
||||||
types::{
|
types::{
|
||||||
Channel, ChannelCreateSchema, Guild, GuildCreateSchema, RegisterSchema,
|
Channel, ChannelCreateSchema, Guild, GuildCreateSchema, RegisterSchema,
|
||||||
RoleCreateModifySchema, RoleObject, Shared,
|
RoleCreateModifySchema, RoleObject, Shared
|
||||||
},
|
},
|
||||||
UrlBundle,
|
UrlBundle,
|
||||||
};
|
};
|
||||||
|
@ -59,12 +59,9 @@ impl TestBundle {
|
||||||
|
|
||||||
// Set up a test by creating an Instance and a User. Reduces Test boilerplate.
|
// Set up a test by creating an Instance and a User. Reduces Test boilerplate.
|
||||||
pub(crate) async fn setup() -> TestBundle {
|
pub(crate) async fn setup() -> TestBundle {
|
||||||
|
|
||||||
// So we can get logs when tests fail
|
// So we can get logs when tests fail
|
||||||
let _ = simple_logger::SimpleLogger::with_level(
|
let _ = simple_logger::SimpleLogger::with_level(simple_logger::SimpleLogger::new(), log::LevelFilter::Debug).init();
|
||||||
simple_logger::SimpleLogger::new(),
|
|
||||||
log::LevelFilter::Debug,
|
|
||||||
)
|
|
||||||
.init();
|
|
||||||
|
|
||||||
let instance = Instance::new("http://localhost:3001/api").await.unwrap();
|
let instance = Instance::new("http://localhost:3001/api").await.unwrap();
|
||||||
// Requires the existence of the below user.
|
// Requires the existence of the below user.
|
||||||
|
@ -144,9 +141,5 @@ pub(crate) async fn setup() -> TestBundle {
|
||||||
pub(crate) async fn teardown(mut bundle: TestBundle) {
|
pub(crate) async fn teardown(mut bundle: TestBundle) {
|
||||||
let id = bundle.guild.read().unwrap().id;
|
let id = bundle.guild.read().unwrap().id;
|
||||||
Guild::delete(&mut bundle.user, id).await.unwrap();
|
Guild::delete(&mut bundle.user, id).await.unwrap();
|
||||||
bundle
|
bundle.user.delete().await.unwrap()
|
||||||
.user
|
|
||||||
.delete(DeleteDisableUserSchema { password: None })
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue